Загрузка файла без активации
Как вы обрабатываете загрузку файлов в рельсе, не привязывая их к активной записи?
Я просто хочу записать файлы на диск.
Спасибо,
Ответы
Ответ 1
Если я правильно понимаю, что вам нужно, самым простым примером будет следующее:
Контроллер:
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 больше не поддерживается. Эти драгоценные камни позволят вам проверить, что вы загружаете, чтобы сделать его более разумным.
Ответ 2
Вы можете просто переместить временный файл на путь судьбы, используя 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
Ответ 3
Документация 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)
является более кратким, если не быстрее.
Ответ 4
Вы можете попробовать использовать плагин Rails Attachment_fu для обработки загрузки файлов. Он позволяет сохранять загрузки в файловую систему вместо базы данных.