В 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 завершена, удалите файл с сервера.
Любая помощь по этому поводу будет высоко оценена.
Спасибо,
Четан
Ответы
Ответ 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)