Как вы обрабатываете загрузку файлов в рельсе, не привязывая их к активной записи?
Я просто хочу записать файлы на диск.
Спасибо,
Как вы обрабатываете загрузку файлов в рельсе, не привязывая их к активной записи?
Я просто хочу записать файлы на диск.
Спасибо,
Если я правильно понимаю, что вам нужно, самым простым примером будет следующее:
Контроллер:
class UploadController < ApplicationController
def new
end
def create
name = params[:upload][:file].original_filename
path = File.join("public", "images", "upload", name)
File.open(path, "wb") { |f| f.write(params[:upload][:file].read) }
flash[:notice] = "File uploaded"
redirect_to "/upload/new"
end
end
Вид:
<% flash.each do |key, msg| %>
<%= content_tag :div, msg, :class => [key, " message"], :id => "notice_#{key}" %>
<% end %>
<% form_tag '/upload/create', { :multipart => true } do %>
<p>
<%= file_field_tag 'upload[file]' %>
</p>
<p>
<%= submit_tag "Upload" %>
</p>
<% end %>
Это позволит вам загружать любой файл без каких-либо проверок или проверок, которые, на мой взгляд, не так полезны.
Если бы я сделал это сам, я бы использовал что-то вроде validatable gem или без табличного камня, только tableless больше не поддерживается. Эти драгоценные камни позволят вам проверить, что вы загружаете, чтобы сделать его более разумным.
Вы можете просто переместить временный файл на путь судьбы, используя FileUtils
tmp = params[:my_file_field].tempfile
destiny_file = File.join('public', 'uploads', params[:my_file_field].original_filename)
FileUtils.move tmp.path, destiny_file
Документация Tempfile
показывает пример, эквивалентный коду Rytis, который отлично работает в большинстве случаев. Но когда вы вызываете tempfile.read
, Ruby считывает весь файл в виде одного фрагмента в память, что является субоптимальным.
Однако FileUtils
предоставляет метод copy_stream
, а IO
, по крайней мере, в Ruby 2.0, предоставляет copy_stream
реализация, которая обрабатывает прямое обращение к пути к файлу (FileUtils.copy_stream
требует файлов с похожими файлами с обеих сторон, или так говорят документы).
В моем случае я инициировал большую загрузку нескольких файлов через AJAX и хотел не читать весь файл в памяти Ruby перед записью на диск.
В приведенном ниже примере params[:files]
- это Array
экземпляров ActionDispatch::Http::UploadedFile
, а local_filepath
- строка, указывающая на несуществующий файл в существующем каталоге. Для краткости я предполагаю, что я загружаю только один файл:
IO.copy_stream(params[:files][0].tempfile, local_filepath)
В экземпляре ActionDispatch::Http::UploadedFile
есть поле .tempfile
, которое является обычным экземпляром Tempfile
.
Я не уверен, что Ruby все еще не читает весь файл в памяти - я ничего не тестировал, но это намного более возможно, чем с синтаксисом localfile.write(tempfile.read)
.
tl; dr: IO.copy_stream(your_tempfile, your_disk_filepath)
является более кратким, если не быстрее.
Вы можете попробовать использовать плагин Rails Attachment_fu для обработки загрузки файлов. Он позволяет сохранять загрузки в файловую систему вместо базы данных.