web-dev-qa-db-ja.com

Ruby on Railsの場合)send_fileメソッドの後にサーバーからファイルを削除します

Railsでファイルを送信するために次のコードを使用しています。

 if File.exist?(file_path)
 send_file(file_path、type: 'text/Excel')
 File.delete(file_path)
 end 

これで私はファイルを送信し、それが正常に送信されたらサーバーからファイルを削除しようとしています。しかし、私が直面している問題は、送信の実行中に削除操作が実行されるため、ブラウザに何も表示されないことです。

Railsには何らかの方法があります。send_file操作が完了したら、サーバーからファイルを削除します。

これについて何か助けていただければ幸いです。

おかげで、
チェタン

32
Chetan Kalore

send_fileを使用しているため、RailsはリクエストをHTTPサーバー(nginx、Apacheなど)に渡します- Rails X-Sendfileヘッダーに関するsend_fileのドキュメント )このため、ファイルを削除しようとしたときに、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)

もう1つのオプションは、削除する一時ファイルを定期的にチェックするバックグラウンドジョブです。

38
Dylan Markow

送信しようとしているファイルをその場で生成する場合、解決策は 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の更新によるものであることを確認できなかったため、.

4
louije

これは私のために働きます! 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)
1
kristina