我有多个文件设置,但它需要多个文件字段,但我只需要一个文件字段.如果浏览器不支持HTML5 multiple属性,我将提供此默认值.
调节器
def new @ad = Ad.new 5.times { @ad.images.build } // provIDes multiple file fIElds in the vIEw.enddef create ad = Ad.new(params[:ad]) user = User.find(session[:user_ID]) if user.ads << ad flash[:notice] = "Ad successfully saved." redirect_to ad_Listing_path(ad.ID,ad.slug) else render :new,:alert => "Ad was not saved." endend
视图
<%= f.fIElds_for :images do |a| %> <% if a.object.new_record? %> <%= a.file_fIEld :image,:multiple => true %><br> <% end %><% end %>
如果5次{@ ad.images.build}提供我的多个字段,那么显示1个接受多个字段的文件字段的正确方法是什么?
解决方法 这似乎是一个没有好答案的热门问题,所以我将在这里完全回答.在开始之前,我将提到代码在 https://github.com/mdchaney/multi处可用,但请继续查看如何以最简单的方式执行此 *** 作.在我们去那里之前,在HTML 5中,文件输入字段可以具有“多个”属性集.如果已设置,则结果与具有相同名称的多个文件输入相同.在Rails中,为表单构建器构建的文件输入字段设置“multiple:true”将使其作为文件数组上载.
<%= f.file_fIEld :files,:multiple => true %>
变
<input ID="model_files" multiple="multiple" name="model[files][]" type="file" />
其中“model”是模型的名称.此输入控件将(至少在Chrome中)具有“选择文件”标签而不是“选择文件”.
CarrIErWave本身不能处理这个问题.它使用单个文本字段来存储有关单个文件的信息,以及一些内部逻辑来确定存储该文件(及其衍生物)的位置.有可能破解它将多个文件的信息放在单个文本字段中,选择具有set分隔符的编码.这需要在CarrIErWave上进行大量的工作和黑客攻击.
但是,我并不关心破解CarrIErWave,所以问题变成了这样一个事实,即将多个文件附加到一个项目实际上是一对多的关系,或者在Rails术语中是“has_many”.因此,可以使用简单的属性编写器将文件输入字段中的文件添加到多个附加记录中.
有了这个,我提出了最简单的方法来使用带有多个属性集的HTML 5文件输入字段.有很多方法可以用jquery和flash做到这一点,但我现在用它来展示如何用直接的HTML 5来实现它.
在我们的示例中,我们将有一个简单的“上传”模型,每个模型都有一个名称和任意数量的链接文件,这些文件将存储在另一个名为linked_files的模型中(使其变得简单,对吧?). linked_file将保存原始文件名,提供内容类型,当然还有CarrIErWave存储其信息的字段.
让我们为上传创建脚手架,然后创建linked_files的模型:
rails g scaffold Upload name:stringrails g model linkedfile upload:references filename:string mime_type:string file:string
完成后,如果我们希望在字段上添加“非null”约束,我们可以设置限制:
class CreateUploads < ActiveRecord::Migration def change create_table :uploads do |t| t.string :name,limit: 100,null: false t.timestamps end endendclass Createlinkedfiles < ActiveRecord::Migration def change create_table :linked_files do |t| t.references :upload,null: false t.string :filename,limit: 255,null: false t.string :mime_type,null: false t.string :file,null: false t.timestamps end add_index :linked_files,:upload_ID endend
现在,让我们通过添加一个名为“files”的新属性writer来修复Upload模型:
class Upload < ActiveRecord::Base has_many :linked_files,inverse_of: :upload,dependent: :destroy accepts_nested_attributes_for :linked_files,reject_if: :all_blank,allow_destroy: true valIDates_associated :linked_files attr_accessible :name,:files,:linked_files_attributes def files=(raw_files) raw_files.each do |raw_file| self.linked_files.build({filename: raw_file.original_filename,mime_type: raw_file.content_type,file: raw_file}) end end valIDates :name,presence: true,length: { maximum: 100 }end
其中大部分是Rails模型的正常声明.这里唯一真正的补充是“files =”方法,它将一组上传的文件放在一个数组中,并为每个文件创建一个“linked_file”.
我们需要一个CarrIErWave上传器:
class fileUploader < CarrIErWave::Uploader::Base storage :file def store_dir "uploads/#{model.class.to_s.underscore}/#{model.ID}/#{mounted_as}" endend
这是最简单的上传器,您可能希望限制上传的文件类型或其他.现在,linkedfile模型:
class linkedfile < ActiveRecord::Base mount_uploader :file,fileUploader belongs_to :upload,inverse_of: :linked_files attr_accessible :file,:filename,:mime_type,:file_cache,:remove_file valIDates :filename,length: { maximum: 255 } valIDates :mime_type,length: { maximum: 255 }end
这没什么特别的,只添加了:file_cache和:remove_file作为文件上传器的可访问属性.
除了观点之外,我们现在已经完成了.我们实际上只需要更改表单,但我们也会更改“show”以允许访问上传的文件.这是_form.HTML.erb文件:
<%= form_for(@upload,{ multipart: true }) do |f| %> <% if @upload.errors.any? %> <div ID="error_explanation"> <h2><%= pluralize(@upload.errors.count,"error") %> prohibited this upload from being saved:</h2> <ul> <% @upload.errors.full_messages.each do |msg| %> <li><%= msg %></li> <% end %> </ul> </div> <% end %> <div > <%= f.label :name %><br /> <%= f.text_fIEld :name %> </div> <% if f.object.linked_files.size == 0 -%> <div > <%= f.label :files %><br /> <%= f.file_fIEld :files,:multiple => true %> </div> <% else -%> <fIEldset> <legend>linked files</legend> <%= f.fIElds_for :linked_files do |lff| -%> <div > <%= lff.label :filename %><br /> <%= lff.text_fIEld :filename %> </div> <div > <%= lff.label :mime_type %><br /> <%= lff.text_fIEld :mime_type %> </div> <div > <%= lff.label :file,'file (replaces current selection)' %><br /> <%= lff.file_fIEld :file %> <%= lff.hIDden_fIEld :file_cache %> </div> <div > <%= lff.check_Box :_destroy %> Remove this file </div> <hr /> <% end -%> </fIEldset> <% end -%> <div > <%= f.submit %> </div><% end %>
我添加了两段代码.如果@upload对象没有与之关联的“linked_files”,我只显示多个文件输入.否则,我会向每个linked_file显示其所有信息.可以向上传添加“文件”方法并以这种方式处理它,但这样做会在请求中丢失mime类型.
您可以轻松测试此内容,因为上传“名称”是必填字段.启动服务器并转到http://127.0.0.1:3000/uploads以查看该应用程序.单击“新建”链接,选择一些文件并点击“创建上传”而不提供名称.下一页将显示您正在等待的所有文件.添加名称时,所有内容都会保存.让我们修改“show”动作来显示linked_files:
<p ID="notice"><%= notice %></p><p> <b>name:</b> <%= @upload.name %></p><p> <b>files:</b><br /></p><table> <thead><tr><th>Original filename</th><th>Content Type</th><th>link</th></tr></thead> <tbody> <% @upload.linked_files.each do |linked_file| -%> <tr> <td><%= linked_file.filename %></td> <td><%= linked_file.mime_type %></td> <td><%= link_to linked_file.file.url,linked_file.file.url %></td> </tr> <% end -%> </tbody></table><%= link_to 'Edit',edit_upload_path(@upload) %> |<%= link_to 'Back',uploads_path %>
在这里我只添加了一个“文件”标题和一个显示所有这些标题的表,并提供了一个查看链接.没什么好看的,但它确实有效.
如果我将它变成一个真正的应用程序,我也可能会提供一个文件列表或上传索引页面上最少的文件数.
就是这样了.再次,如果你想下载它,整个测试应用程序可以在github上获得,但我已经把我的整个Rails生成语句和更改发布在这篇文章中.
总结以上是内存溢出为你收集整理的ruby-on-rails-3 – Rails 3.2 HTML5多文件上传,Carrierwave,没有Javascript全部内容,希望文章能够帮你解决ruby-on-rails-3 – Rails 3.2 HTML5多文件上传,Carrierwave,没有Javascript所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)