rails - x-sendfile + временные файлы - PullRequest
8 голосов
/ 18 мая 2011

Некоторое время назад я написал вопрос относительно использования временных файлов в приложении rails.В этом конкретном случае я решил использовать tempfile

Это вызывает проблему, если я также хочу использовать директиву x-sendfile ( в качестве параметра в Rails 2 или какопция конфигурации в Rails 3 ), чтобы отправка файлов осуществлялась непосредственно моим веб-сервером, а не моим приложением rails.

Итак, я подумал о том, чтобы сделать что-то вроде этого:1014 * Эта настройка имеет одну проблему: файл удаляется перед отправкой!

С одной стороны, tempfile удалит файл, как только закончится блок Tempfile.open.С другой стороны, x-sendfile делает вызов send_file асинхронным - он очень быстро возвращается, поэтому у сервера едва ли есть время для отправки файла.

Мое лучшее возможное решение сейчас заключается в использовании невременных файлов (вместо файлаof Tempfile), а затем задача cron, которая периодически удаляет временную папку.Это немного не элегантно, поскольку:

  • Я должен использовать собственную схему именования временных файлов
  • Файлы остаются в папке tmp дольше, чем нужно.

Есть ли лучшая настройка?Или, по крайней мере, есть «успешный» обратный вызов для асинхронного send_file, поэтому я могу стереть f, когда это будет сделано?

Большое спасибо.

Ответы [ 4 ]

2 голосов
/ 14 июля 2012

Учитывая, что Rails3 использует x-sendfile, когда он доступен, и деактивировать его невозможно, вы просто не можете использовать send_file с такой библиотекой, как TempFile. Наилучший вариант - тот, который я упомянул в вопросе: используйте обычный файл и задайте задачу cron, которая периодически удаляет старые временные файлы.

РЕДАКТИРОВАТЬ: теперь удаление неиспользуемых файлов стало проще с самоцветом горничной:

https://github.com/benjaminoakes/maid

0 голосов
/ 27 сентября 2013

Вы можете отменить определение финализатора экземпляра Tempfile, чтобы ваш файл никогда не удалялся при удалении экземпляра, а затем позволить задаче chron обработать его.

require 'tempfile'

def foo()
  # creates a temporary file in tmp/
  Tempfile.open('prefix', "#{Rails.root}/tmp") do |f|
    f.print('a temp message')
    f.flush
    ObjectSpace.undefine_finalizer(f) # 'disables' deletion when GC'ed
    send_file(f.path, :x_sendfile => true) # send_file f.path in rails 3
 end
end
0 голосов
/ 24 мая 2011

Как насчет файла-temp gem? https://github.com/djberg96/file-temp

require 'file/temp'

fh = File::Temp.new(false)
fh.puts "world"
fh.close # => Tempfile still on your filesystem

Как и в случае с ответом zzzhc, вам потребуется внешнее управление очисткой

0 голосов
/ 18 мая 2011

не помещайте send_file в блок.

f = Tempfile.new('prefix', "#{Rails.root}/tmp")
f.print('a temp message')
f.close
send_file(f.path, :x-sendfile => true)

затем используйте другой скрипт для очистки временного файла

...