RubyFile.exist? returns 在文件可读之前为真

Ruby File.exist? returns true before file is readable

我有一个 Rails 应用程序,我试图将大型 PDF 的创建过程传递给后台进程,并允许用户在完成后查看它。这是一个多页文档,结合 combine_pdf gem 并传递给 delayed_job.

我有 3 个操作:第一个创建并保存文件,第二个通过异步请求以短延迟重复调用以检查文件是否存在,第三个在浏览器中显示 PDF。

我在处理第二部分时遇到了问题,因为它使用了 File.exist?('my_file.pdf'),但它在文件完成保存之前就返回了 true。然后显示的 link 查看 PDF 导致错误 (ActionController::MissingFile)。该文件实际上在大约 10 秒后可用,此时 link 正常工作。

我猜文件在检查时仍在写入?如何检查文件保存是否已完成,文件是否确实可供读取?

您可以写入一个临时文件,然后在完成后重命名它。到目前为止你还没有包含你的代码,但这样的东西可能对你有用:

def write_and_replace(path, file, file_name, data)
  file_path = File.join(folder_path, "#{file_name}.pdf")
  temp_file_path = File.join(folder_path, "temp_#{file_name}.pdf")

  File.open(temp_file_path, 'w') { |f| f.write(data) }

  # Args: existing file, new name
  File.rename(path, file_path)
  File.rename(temp_file_path, file)
  File.delete(file_path)
end

我是这样做的(非常宽泛且有些粗略):

首先,我在调用后台创建进程的控制器上调用 post 操作。此操作会创建一个 ServiceRequest(我的应用程序中的一个模型),具有相关的 service_request.details 和状态 created。然后 service_request 被发送到后台进程(我使用 RabbitMQ)。而动作 returns service_request.id.

前端开始ping(通过AJAX)服务请求端点(类似于service_requests/:id),ServiceRequestControllershow动作发回service_request.status(以及其他内容,包括 service_request.results。当 service_request.status 既不是 completed 也不是 failed 时循环。

同时,后台进程创建 PDF。完成后,它将 service_request.status 设置为 completed。并且,它设置 service_request.results 以包含前端定位和检索 PDF 所需的数据。 (因为我在 Heroku 上,所以我将我的 PDF 存储到 AWS 存储桶。)

当前端最终收到 completed 的 service_request.status 时,它使用 service_request.results 来获取和显示 PDF。