In Ruby on Rails, After send_file method delete the file from server

后端 未结 3 751
执笔经年
执笔经年 2020-12-05 02:16

I am using following code for sending the file in Rails.

if File.exist?(file_path)
  send_file(file_path, type: \'text/excel\') 
  File.delete(file_path)
end


        
相关标签:
3条回答
  • 2020-12-05 02:52

    If you are generating on the fly the file you are trying to send, a solution is to use the Tempfile class:

    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
    

    Contrary to what is indicated in this question, this works as expected (the file stays on the server long enough to be served, but ultimately gets deleted); this post seems to indicate this is due to updates in Rails 3.2.11, something I couldn’t verify.

    0 讨论(0)
  • 2020-12-05 02:53

    This works for me! With send_data you can delete file before send.

    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)
    
    0 讨论(0)
  • 2020-12-05 03:00

    Because you're using send_file, Rails will pass the request along to your HTTP server (nginx, apache, etc. - See the Rails documentation on send_file regarding X-Sendfile headers). Because of this, when you try to delete the file, Rails doesn't know that it's still being used.

    You can try using send_data instead, which will block until the data is sent, allowing your File.delete request to succeed. Keep in mind that send_data requires a data stream as its argument though, not a path, so you need to open the file first:

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

    The other option would be a background job that periodically checks for temp files to delete.

    0 讨论(0)
提交回复
热议问题