Rails: Send a file to user

Изпращането на файл към потребителя е доста тривиална задача, и начинът по който можете да я постигнете с Rails е относително лесен – основната функция за целта е send_file, която, според документацията би трябвало да прави следното:

Sends the file by streaming it 4096 bytes at a time. This way the whole file doesn‘t need to be read into memory at once. This makes it feasible to send even large files

Да, ама не. Ако ползвате mongrel (което правят 90% от rails developer-ите), файлът изобщо не се разбива на парчета от по 4096 bytes, а се качва целия в паметта.

Алтернтивен вариант е да използвате опцията send_data, но пък тя изисква buffer с данни, за да изпълни нормално работата си. Ето пример как можете да изпратите файл с помощта на send_data:

def download
  send_data IO.read('path/to.file'), :filename=>'somename.ext'
end

Третият, и поне според мен най-чист, метод е да оставите цялата работа по връщането на файловете на web-сървъра, който ползвате като frontend.

В случай, че ползвате Apache или Lighttpd, методът за изпращане на файл до потребителя ще трябва да изглежда така:

def download
  response.headers['X-Sendfile'] = 'path/to.file';
  render :nothing => true
end

Ако изборът ви е паднал върху Nginx – ето вариант на метода, с който ще постигнете същото:

def download
  response.headers['X-Accel-Redirect'] = 'path/to.file';
  render :nothing => true
end

При мен download URL-a не работеше по подразбиране, връщайки ActiveRecord::RecordNotFound, защото контролера който ползвах отразяваше REST ресурс. За да го накарам да работи във файла /config/routes.rb се наложи да заменя следния ред:

map.resources :download_demo

със следното:

map.resources :download_demo, :collection => {:download => :get}

Маркери: , ,

За тази статия



Категории

Подобни статии