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
),ServiceRequestController
的show
动作发回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。
我有一个 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
),ServiceRequestController
的show
动作发回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。