14

我正在寻找一种解决方案,让用户能够通过一个 file_field 上传多个图像。我已经研究过诸如 Jquery File Upload 和 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 个单独的 file_fields

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 %>

这允许用户在他们的文件浏览器中选择多个文件。但是如何使用嵌套模型处理这些?并让他们上传。

4

3 回答 3

35

所以这里有几个问题。

首先,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 是一个不错的选择(我以前使用过)。有一个 gem 可以转换文件字段以使用 uploadify (并将支持:multiple => true您想要的语法):https ://github.com/mateomurphy/uploadify_rails3/ wiki . 但是,我不能保证它有多好。

我的建议是逐步开始。通过 Flash 上传到 Rails 可能是一个复杂的过程,涉及处理 CSRF 元标记和表单中的其他字段。首先制作一个表单,允许用户上传一个文件并通过 Paperclip 存储它。然后可以将has_attached_file声明分解为另一个模型,以便您可以拥有一个或多个与模型关联的文件(如上面的多模型代码块所示)。然后尝试添加 Uploadify 或其他替代方法。Ernie Miller 有一个关于集成 Uploadify 的不错的教程:http: //erniemiller.org/2010/07/09/uploadify-and-rails-3/

首先,请记住has_attached_file只能附加一个文件。当您尝试调用@listing.assets时,没有“资产”。有资产。如果需要多个文件,您需要自己创建一个单独的模型并使用 Rails 的关联。

于 2012-06-06T21:30:09.043 回答
7

接受的答案说没有像 HTML 中的多个文件上传这样的东西。

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

这允许您选择多个图像并将它们作为数组发送。

如果您有 和 的关系Dog has_many ImagesImage 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

这是假设您已经能够上传一张图片但想一次升级到多张图片。请注意,等待时间会增加。

为了帮助减少等待时间,请查看我关于这个与速度上传相关的问题的帖子。

于 2017-01-10T05:26:01.183 回答
2

这是多个文件上传的完整示例。这里一个user has_many uploads. 每个upload模型都有一个avatar代表文件附件的。最终:uploads当我们创建user.

模型

#models/user.rb
class User < ApplicationRecord
  has_many :uploads

  def files=(array_of_files = [])
    array_of_files.each do |f|
      uploads.build(avatar: f, user: self)
    end
  end
end


#models/upload.rb
class Upload < ApplicationRecord
  belongs_to :user

  has_attached_file :avatar
  validates_attachment_content_type :avatar, :content_type => ["image/png"]
end

表格:

# views/users/_form.html.erb
<%= form_with(model: user, local: true) do |form| %>

  ...

  <div class="field">
    <%= form.file_field :files, multiple: true %>
  </div>

  <div class="actions">
    <%= form.submit %>
  </div>
<% end %>

控制器

class UsersController < ApplicationController
  before_action :set_user, only: [:show]

  def show
  end

  def new
    @user = User.new
  end

  def create
    @user = User.new(user_params)

    if @user.save
      redirect_to @user, notice: 'User was successfully created.'
    end
  end

  private
    def set_user
      @user = User.find(params[:id])
    end

    def user_params
      params.require(:user).permit(:name, files: [])
    end
end

用户#show

<p id="notice"><%= notice %></p>

<p>
  <strong>Name:</strong>
  <%= @user.name %>
</p>


<h3>Uploads</h3>
<div>
  <% @user.uploads.each do |upload|  %>
    <div>
      <%= link_to upload.avatar.url do%>
        <%= upload.avatar_file_name %>
      <% end %>
    </div>
  <% end %>
</div>

<%= link_to 'Edit', edit_user_path(@user) %> |
<%= link_to 'Back', users_path %>
于 2019-03-08T18:13:38.127 回答