Подтвердить что ты не робот

В 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 завершена, удалите файл с сервера.

Любая помощь по этому поводу будет высоко оценена.

Спасибо,
Четан

4b9b3361

Ответ 1

Поскольку вы используете send_file, Rails передаст запрос вместе с вашим HTTP-сервером (nginx, apache и т.д. - См. документацию Rails на send_file относительно заголовков X-Sendfile). Из-за этого, когда вы пытаетесь удалить файл, 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)

Другим вариантом будет фоновая работа, которая периодически проверяет, чтобы временные файлы удалялись.

Ответ 2

Если вы генерируете "на лету" файл, который вы пытаетесь отправить, следует использовать 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, что я не смог проверить.

Ответ 3

Это работает для меня! С помощью 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)