38

我正在使用以下代码在 Rails 中发送文件。

如果 File.exist?(file_path)
  发送文件(文件路径,类型:'文本/excel')
  File.delete(file_path)
结尾

在此我试图发送文件并在成功发送后从服务器中删除文件。但我面临的问题是,删除操作正在执行发送时执行,因此我在浏览器中看不到任何内容。

那么 Rails 有什么办法,一旦 send_file 操作完成,就从服务器中删除文件。

对此的任何帮助将不胜感激。

谢谢,
切坦

4

3 回答 3

50

因为您正在使用send_file,Rails 会将请求传递到您的 HTTP 服务器(nginx、apache 等 -请参阅关于 X-Sendfile 标头的 send_file 上的 Rails 文档)。因此,当您尝试删除该文件时,Rails 并不知道它仍在使用中。

您可以尝试使用send_data,它会一直阻塞,直到数据发送完毕,让您的File.delete请求成功。请记住,它send_data需要数据流作为其参数,而不是路径,因此您需要先打开文件:

File.open(file_path, 'r') do |f|
  send_data f.read, type: "text/excel"
end
File.delete(file_path)

另一种选择是定期检查要删除的临时文件的后台作业。

于 2013-08-14T12:51:35.283 回答
6

如果您正在动态生成要发送的文件,则解决方案是使用Tempfile该类:

begin
  # The second argument is optional:
  temp_file = Tempfile.new(filename, temp_directory)

  # ... edit temp_file as needed.

  # By default, temp files are 0600,
  # so this line might be needed depending on your configuration:
  temp_file.chmod(0644)
  send_file temp_file
ensure
  temp_file.close
end

此问题中所指出的相反,这按预期工作(文件在服务器上停留的时间足够长,可以提供服务,但最终会被删除);这篇文章似乎表明这是由于 Rails 3.2.11 中的更新,我无法验证。

于 2014-04-19T03:52:47.477 回答
4

这对我有用!您可以在send_data发送前删除文件。

file = File.open(Rails.root.join('public', 'uploads', filename), "rb")
contents = file.read
file.close

File.delete(filepath) if File.exist?(filepath)

send_data(contents, :filename => filename)
于 2014-12-03T16:18:19.713 回答