rails 上传附件
今天做了个上传附件的功能,记录一下
用的gem
gem 'carrierwave' gem 'rmagick', '2.13.2' gem 'mime-types'
关于这些gem都是什么作用这里就不做解释了,github中有介绍。执行bundle,期间会出现一些问题,install rmagick的时候会报错,原因貌似版本的问题。我的系统是ubuntu 12.0.4,解决方法
1、sudo apt-get install libmagickwand-dev
2、sudo gem install rmagick
直接上代码吧,其实上传附件的情景有很多,image、pdf等等,这里我以imag为例。
rails generate uploader Attachment
有了carrierwave的gem包,创建一个uploader,这个uploader会跟普通的model有所区分。会生成一个attachment_uploader.rb的文件
# encoding: utf-8 class AttachmentUploader < CarrierWave::Uploader::Base include CarrierWave::RMagick include CarrierWave::MimeTypes #默认使用file系统 storage :file #文件保持路径,这里就是用默认的 def store_dir "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}" end #定依set_conditent_type的process process :set_content_type #定义thumb格式的style,可以通过rmagick来将上传的图片进行处理 version :thumb, :if => :image? do process :resize_to_fit => [50,50] end #同时定义一中thumb version :preview, :if => :image? do process :resize_to_fit => [80,80] end #为了避免处理一些非image的附件 def image?(file) file.content_type.include? 'image' end end
创建一个attachment的model
rails g model attachment
修改migration
class CreateAttachments < ActiveRecord::Migration def change create_table :attachments do |t| t.string :file_name t.string :content_type t.string :attachmentable_type t.string :file_size t.integer :attachmentable_id t.string :attachment t.timestamps end end end
需要指出的是这里用到了association中的多态方法,考虑到并不值一种model会有attachment,用多态最好了
class Attachment < ActiveRecord::Base mount_uploader :attachment, AttachmentUploader attr_accessible :attachment, :attachmentable #多态 ==>attachmentable表示多种实体 belongs_to :attachmentable, :polymorphic => true validates :attachmentable, :presence => true validates :attachment ,:presence => true before_save :set_attachment_attributes protected #设置附件的属性 def set_attachment_attributes if attachment.present? && attachment_changed? self.content_type = attachment.file.content_type self.file_size = attachment.file.size self.file_name = attachment.file.original_filename end end end
对应view中的_form.html.erb的局部模板
<!--关键地方设置:html => {:multipart => true } --> <%= form_for(@base_info, :html => {:multipart => true}) do |f| %> <% if @base_info.errors.any? %> <div id="error_explanation"> <h2><%= pluralize(@base_info.errors.count, "error") %> prohibited this base_info from being saved:</h2> <ul> <% @base_info.errors.full_messages.each do |msg| %> <li><%= msg %></li> <% end %> </ul> </div> <% end %> <div class="field"> <%= f.label :name %><br /> <%= f.text_field :name %> </div> <div class="field"> <%= f.label :description %><br /> <%= f.text_area :description %> </div> <!-- 添加一个<input type="file"> --> <div class="field"> <label>logo</label> <%= file_field_tag :attachment %> </div> <div class="actions"> <%= f.submit %> </div> <% end %>
在对应的controller的create的方法中
def create @base_info = BaseInfo.new(params[:base_info]) respond_to do |format| if @base_info.save Attachment.create(:attachment => params[:attachment], :attachmentable => @base_info) if params[:attachment] format.html { redirect_to @base_info, notice: 'Base info was successfully created.' } format.json { render json: @base_info, status: :created, location: @base_info } else format.html { render action: "new" } format.json { render json: @base_info.errors, status: :unprocessable_entity } end end end
在显示中就可以得到上传的图片了
<% @base_info.attachments.each do |attachment| %>
<%= image_tag attachment.attachment.thumb %>
<%= image_tag attachment.attachment.url %>
<%= image_tag attachment.attachment.preview %>
<% end %>
查看public就可以看到上传的图片,需要说明的是会有3套图片,因为使用了rmagick的gem。
还可以用