Подтвердить что ты не робот

Rails Paperclip и несколько загрузок файлов

Я ищу решение, позволяющее пользователю загружать несколько изображений через одно файловое поле. Я заглянул в такие опции, как загрузка файлов Jquery и Uploadify, но пока не нашел хороших примеров с рабочим решением.

У меня уже установлена ​​несколько изображений,

 has_attached_file :asset,
                   :styles => { :large => "640x480", :medium => "300x300", :thumb => "100x100" },
                   :storage => :s3,
                   :s3_credentials => "#{Rails.root}/config/s3.yml",
                   :path => "/:contributor_id/:listing_name/:filename"

Сейчас я показываю 5 отдельных файловых полей

def new
  @listing = Listing.new
  5.times {@listing.assets.build }

  respond_to do |format|
    format.html # new.html.erb
    format.json { render json: @listing }
  end
end

Я хотел бы иметь

<%= f.file_field :asset, :multiple => true %>

Это позволяет пользователю выбирать несколько файлов в своем браузере файлов. Но как я могу обработать их с помощью вложенной модели? И попросите их загрузить.

4b9b3361

Ответ 1

Итак, здесь есть несколько проблем.

Во-первых, метод Paperclip has_attached_file не является ассоциацией со многими файлами. Похоже, вы пытаетесь создать "актив", как если бы это была ассоциация Rails. Все файлы Paperclip помещают пару полей в вашу таблицу для хранения некоторых метаданных о файле, и вы получаете один прикрепленный файл на объявление has_attached_file. Если вы хотите прикрепить 5 файлов, вам нужно будет сделать что-то вроде:

has_attached_file :asset1
has_attached_file :asset2
has_attached_file :asset3
has_attached_file :asset4
has_attached_file :asset5

ИЛИ, альтернативно, вы можете создать другую модель только для хранения файлов. Например:

class Listing < ActiveRecord::Base
  has_many :assets
end

class Asset < ActiveRecord::Base
  belongs_to :listing
  has_attached_file :picture
end

Таким образом, у вас может быть несколько активов, прикрепленных к одному листингу (вы не сказали, что такое исходный объект, поэтому я просто назвал его "листинг" ).

Во-вторых, нет такой вещи, как множественная загрузка файла в HTML (и, как таковой, метод file_field не принимает аргумент :multiple => true. Вам нужно будет использовать что-то помимо встроенных Rails если вы хотите загрузить несколько файлов. Uploadify - это достойный выбор (который я использовал раньше). Существует камень, который преобразует поля файлов, чтобы использовать uploadify (и будет поддерживать синтаксис :multiple => true, который вы хотите): https://github.com/mateomurphy/uploadify_rails3/wiki Однако я не могу ручаться за то, насколько он хорош.

Моим советом было бы поэтапно начать. Загрузка через Flash to Rails может быть сложным процессом, связанным с метатегами CSRF и другими полями в вашей форме. Начните с создания формы, которая позволяет пользователю загружать один файл и хранить его через Paperclip. Затем, возможно, сломайте объявление has_attached_file в другой модели, чтобы вы могли иметь 1 или несколько файлов, связанных с моделью (как показано в многомодовом блоке кода выше). Затем попробуйте добавить Uploadify или другую альтернативу. У Эрни Миллера есть достойный учебник по интеграции Uploadify: http://erniemiller.org/2010/07/09/uploadify-and-rails-3/.

Чтобы начать, помните, что has_attached_file может прикреплять только один файл. Когда вы пытаетесь позвонить @listing.assets, нет "активов". Существует актив. Вам нужно создать отдельную модель самостоятельно и использовать ассоциации Rails, если вы хотите несколько файлов.

Ответ 2

Принятый ответ говорит, что нет такой вещи, как множественная загрузка файла в HTML.

<%= f.file_field :files, multiple: true %>

Это позволяет вам выбирать несколько изображений и отправлять их в виде массива.

Если у вас есть отношения Dog has_many Images и Image has_attachment :file, сделайте это, чтобы сразу загрузить несколько изображений:

В html.erb

<%= form_for @dog, html: { multipart: true } do |f| %>
  <%= f.file_field :files, accept: 'image/png,image/jpeg,image/gif', multiple: true %>
<%= end %>

В вашем контроллере

def dog_params
  params.require(:dog).permit files: []
end

В вашей модели Dog

def files=(array = [])
  array.each do |f|
    images.create file: f
  end
end

Предполагается, что вы уже можете загрузить одно изображение, но хотите обновить сразу несколько изображений. Обратите внимание, что время ожидания увеличится.

Чтобы уменьшить время ожидания, просмотрите мой пост по этому вопросу, связанный с загрузкой скорости.