`

(转)Rails中文件上传

阅读更多
Rails中文件上传
来源: 作者: 发布时间:2007-08-21
 

一。将文件保存到指定的文件夹中,对它重命名,保存重命名后的文件名称

为了能使任何controller都能使用文件上传的功能,变将代码放置在application.rb中

代码
  1. # Filters added to this controller will be run for all controllers in the application.   
  2. # Likewise, all the methods added will be available for all controllers.   
  3. class ApplicationController < ActionController::Base   
  4.    before_filter :configure_charsets     
  5.   
  6.    def configure_charsets           
  7.        @headers["Content-Type"]="text/html;charset=utf-8"       
  8.    end       
  9.      
  10.   def uploadFile(file)     
  11.      if !file.original_filename.empty?   
  12.        #生成一个随机的文件名       
  13.        @filename=getFileName(file.original_filename)          
  14.        #向dir目录写入文件   
  15.        File.open("#{RAILS_ROOT}/public/emag/upload/#{@filename}""wb"do |f|    
  16.           f.write(file.read)   
  17.        end    
  18.        #返回文件名称,保存到数据库中   
  19.        return @filename  
  20.      end   
  21.   end    
  22.   
  23.   def getFileName(filename)   
  24.      if !filename.nil?   
  25.        require 'uuidtools'   
  26.        filename.sub(/.*./,UUID.random_create.to_s+'.')   
  27.      end   
  28.   end       
  29. end  
<script type="text/javascript">render_code();</script>

 

在页面中,我们定义一<%=file_field "object","field"%>

代码
  1. <%=file_field 'book','bgImage'%>  
<script type="text/javascript">render_code();</script>

 

然后在对应的controller中调用即可

代码
  1. def create   
  2.     if request.get?   
  3.       @book=Book.new  
  4.     else  
  5.       @book=Book.new(params[:book])      
  6.       @book.bgImage=uploadFile(params[:book]['bgImage'])    
  7.       if @book.save   
  8.         redirect_to_index   
  9.       end   
  10.     end   
  11.   end  

二。Rails上传文件到数据库(以图片文件为例)

POST message有一种特殊的类型叫做:multipart/form-data,这是一种又一种特定的form产生的message,这种form是包含<input type="file"...>的form。在客户端<input type="file"...>标签显示成这样的形式:

 

为了说明问题,我们举例来看看,先建立数据库:

create table pictures (
  id int not null auto_increment,
  comment varchar(100),
  name varchar(200),
  content_type varchar(100),
  data blob,
  primary key (id)
);

 

 

建立controller:

class UploadController < ApplicationController
  def get
    @picture = Picture.new
  end
end

 

建立get template:

<%= error_messages_for("picture") %>
<%= form_tag({:action => 'save'}, :multipart => true) %>
Comment: <%= text_field("picture", "comment") %>
<br/>
Upload your picture: <%= file_field("picture", "picture") %>
<br/>
<%= submit_tag("Upload file") %>
<%= end_form_tag %>

 

建立model:

class Picture < ActiveRecord::Base
  validates_format_of :content_type, :with => /^image/,
    :message => "--- you can only upload pictures"
  def picture=(picture_field)
    self.name = base_part_of(picture_field.original_filename)
    self.content_type = picture_field.content_type.chomp
    self.data = picture_field.read
  end
  def base_part_of(file_name)
    name = File.basename(file_name)
    name.gsub(/[^\w._-]/, '')
  end
end

 

这里定义的 picture= method,会读取表单中 name=picture[picture] 的标签的数据,因为文件对象比较复杂,不能直接存到数据库中的某个列中,所以需要进行复杂的处理,html中文件对象的可以分为3个部分:

文件的名称 上传时候的文件名字 比如:1.gif
文件的类型 上传的文件的类型 比如:image/gif
文件的数据部分 文件的数据部分  

上面的红色字体对应了处理文件对象的部分

 

 

扩充controller,添加save action:

def save
  @picture = Picture.new(params[:picture])
  if @picture.save

    redirect_to(:action => 'show', :id => @picture.id)
  else
    render(:action => :get)
  end
end

 

 

扩充controller,添加picture action:

def picture
  @picture = Picture.find(params[:id])
    send_data(@picture.data,
    :filename => @picture.name,
    :type => @picture.content_type,
    :disposition => "inline")
end

 

注意send_data method 返回值被 url_for method接受,用于显示图片,我们这里要注意一下 :filename和:type这2个key,在用户使用右键---另存为 的时候,文件名和类型将被显示出来

 

定义show action:

def show
  @picture = Picture.find(params[:id])
end

 

 

show template:

<h3><%= @picture.comment %></h3>
<img src="<%= url_for(:action => "picture", :id => @picture.id) %>"/>

 

这里使用url_for方法来显示图片

三。图片文件上传

假设如下场景,一个用户有一个logo图片,支持上传logo图片功能。这里对显示图片和用户图片关系进行下整合。

entry DDL:

sql 代码
  1. CREATE TABLE `entries` (   
  2.   `id` int(11) NOT NULL auto_increment,   
  3.   `image` varchar(255) NOT NULL,   
  4.   `photoable_id` int(11) NOT NULL,   
  5.   `photoable_type` varchar(100) NOT NULL,   
  6.   PRIMARY KEY  (`id`)   
  7. ) ENGINE=InnoDB DEFAULT CHARSET=utf8  

 

user.rb:

ruby 代码
  1. class User < ActiveRecord::Base   
  2.   has_many :entries:as => :photoable  
  3.      
  4.   def logo_url   
  5.     url = "/images/users/default_logo.gif"  
  6.       if self != nil and self.logo == 1   
  7.       entry = Entry.find(:first, :conditions => "photoable_id = #{self.id}", :order => "uploaded_time desc")  
  8.       relative_path = entry.send("image_relative_path", 'thumb')   
  9.       return nil unless relative_path   
  10.       url = "/entry/image/"  
  11.       url << relative_path   
  12.     end  
  13.     url   
  14.   end  
  15.   
  16. end  

 注意其中的logo_url方法,这个方法参考了file_column中的相关代码直接对图片地址进行了包装。

entry.rb

ruby 代码
  1. class Entry < ActiveRecord::Base      
  2.   belongs_to :photoable:polymorphic => true  
  3.   
  4.   validates_format_of :image,      
  5.     :with=>/^.*(.jpg|.JPG|.gif|.GIF)$/,      
  6.     :message => "你只能上传JPG或则GIF的图片文件"  
  7.        
  8.   file_column :image:magick => {       
  9.           :versions => { "thumb" => "80x80" }      
  10.         }      
  11. end  

 

上述代码实现了user和entry的一对多关系,并且实现了多态。这里需要注意的是logo_url方法,此方法修改了File_Column自带的FileColumnHelper::url_for_file_column方法,原方法只能在ActionView中使用,并且需要一个ActionController中的对象,有些时候不是很方便使用。

感谢原文作者提供的帮助!

 

还有一个需要注意的是,中文文件名上传名称变为"__"的问题,

秦朝古月 给出了解决方案:

file_column上传中文文件名的文件时,汉字变成“_”的解决办法
编辑file_column.rb文件
把方法 self.sanitize_filename(filename)中的
filename.gsub!(/[^a-zA-Z0-9\.\-\+_]/,"_")
给注释掉。

 

原文引用:

在网站制作过程中,图片上传以及图片的大小调整是经常会用到的一个功能!

Rails结合几个plug-in可以说很智能的做到了这一点

做了一个简单的例子,系统在Windows平台上运行

1.上网下载file-column-0.3.1.tar.gz 和rmagick-win32-1.13.0_IM-6.2.9-3.zip (我当前的最新版本,到下述站点下载 http://rubyforge.org/projects/rmagick/ Linux下版本是RMagick-1.14.1.tar.gz)

2.安装rmagick,执行zip包里面的exe文件,同时把安装路径放到path环境变量里面去,否则可能会报CORE_RL_magick_.dll找不到的错误

3.安装file-column到app的vendor目录里,直接copy过去就行

 

引用
以下的文件配置基本上按照官方提供的sample来进行,算是用中文整合一下,谈不上原创


4.建立一个存放路径的model,在数据库中建立Entry数据库
并生成相应的scaffold:
ruby script/generate scaffold Entry upload

 

4.修改model,并限制只能图片上传

代码
  1. class Entry < ActiveRecord::Base   
  2.   validates_format_of :image,   
  3.     :with=>/^.*(.jpg|.JPG|.gif|.GIF)$/,   
  4.     :message => "你只能上传JPG或则GIF的图片文件"  
  5.   file_column :image, :magick => {    
  6.           :versions => { "thumb" => "50x50""medium" => "640x480>" }   
  7.         }   
  8. end  

<script>render_code();</script>

 

5.修改_form.rhtml

代码
  1. <%= error_messages_for 'entry' %>  
  2.   
  3. <!--[form:entry]-->  
  4. <p><label for="entry_image">Imagelabel><br/>  
  5. <%= file_column_field 'entry', 'image'  %>p>  
  6. <!--[eoform:entry]-->  

<script>render_code();</script>

 

6.修改new.rhtml

代码
  1. <h1>New entryh1>  
  2.   
  3. <%= start_form_tag 'create',:multipart => true%>  
  4.   <%= render :partial => 'form' %>  
  5.   <%= submit_tag "Create" %>  
  6. <%= end_form_tag %>  
  7.   
  8. <%= link_to 'Back', :action => 'list' %>  

<script>render_code();</script>

 

7.修改show.rhtml

代码
  1. <% for column in Entry.content_columns %>  
  2. <p>  
  3.   <b><%= column.human_name %>:b> <%=h @entry.send(column.name) %>  
  4.   <br>  
  5.   原始大小:   
  6.   <%= image_tag url_for_file_column 'entry', 'image' %>  
  7.   <br>  
  8.   thumb:   
  9.   <%= image_tag url_for_file_column 'entry', 'image' ,'thumb'%>  
  10.   <br>  
  11.   medium:   
  12.   <%= image_tag url_for_file_column 'entry', 'image' ,'medium'%>  
  13. p>  
  14. <% end %>  
  15.   
  16. <%= link_to 'Edit', :action => 'edit', :id => @entry %> |   
  17. <%= link_to 'Back', :action => 'list' %>  

<script>render_code();</script>

<script type="text/javascript">render_code();</script>
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics