Ruby File.exist?在文件可读之前返回true

时间:2018-11-20 00:09:41

标签: ruby-on-rails ruby pdf delayed-job

我有一个Rails应用程序,试图将大型PDF的创建传递给后台进程,并让用户在完成时可以看到它。这是一个多页文档,结合了Combine_pdf gem,并传递给delay_job。

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

第二部分很麻烦,因为它使用了File.exist?('my_file.pdf'),但这在文件完成保存之前返回了true。然后显示用于查看PDF的链接将导致错误(ActionController :: MissingFile)。该文件实际上在大约10秒钟后可用,此时链接可以正常工作。

我猜该文件在检查时仍在写入?如何检查文件保存已完成并且文件实际上可供读取?

2 个答案:

答案 0 :(得分:1)

您可以写入临时文件,然后在完成后对其重命名。到目前为止,您还没有包含代码,但是类似的事情可能对您有用:

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

答案 1 :(得分:1)

这是(非常广泛且大致而言)我的操作方式:

首先,我在正在调用后台创建过程的控制器上调用post操作。该操作将创建一个具有相关ServiceRequest和状态service_request.details的{​​{1}}(我的应用程序中的模型)。然后created被发送到后台进程(我使用RabbitMQ)。然后该操作返回service_request

前端开始(通过AJAX)对服务请求端点进行ping操作(类似service_request.id),然后service_requests/:id的{​​{1}}操作会发回ServiceRequestController (以及其他内容,包括show。这会在service_request.status既不是service_request.results也不是service_request.status时循环。

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

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