【问题标题】:Ruby File.exist? returns true before file is readableRuby File.exist?在文件可读之前返回 true
【发布时间】:2018-11-20 08:27:44
【问题描述】:

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

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

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

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

【问题讨论】:

  • 就我个人而言,我会保存一些对delayed_job进程的引用,并在读取文件之前检查作业是否已完成,但实现某种临时文件并在保存后移动/重命名它更容易.

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


【解决方案1】:

这是(非常广泛和有点粗略)我是如何做到的:

首先,我在调用后台创建进程的控制器上调用post 操作。此操作创建一个ServiceRequest(我的应用程序中的一个模型),其相关service_request.detailscreated 的状态。然后将service_request 发送到后台进程(我使用RabbitMQ)。该操作返回service_request.id

前端开始 ping(通过 AJAX)服务请求端点(类似于 service_requests/:id),ServiceRequestControllershow 操作发回 service_request.status(以及其他内容,包括 @ 987654331@。这个循环,而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。

【讨论】:

  • 或者通过 Action Cable 推送通知,而不是让客户端轮询。
  • 是的,确实如此。我还没有做 Action Cable,但这似乎是真的。
【解决方案2】:

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

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

【讨论】:

    猜你喜欢
    • 2012-12-22
    • 2012-02-11
    • 1970-01-01
    • 1970-01-01
    • 2021-05-08
    • 2019-10-24
    • 1970-01-01
    • 2021-10-25
    • 1970-01-01
    相关资源
    最近更新 更多