ROR 使用 attachment_fu 上传文件

来源:博客园 链接

http://www.cnblogs.com/yank/archive/2009/11/01/attachment.html

 

 

ROR使用attachment_fu上传附件,很方便,但是配置需要研究。

http://github.com/technoweenie/attachment_fu


migration:

class CreateAttachments  <  ActiveRecord :: Migration
  def self
. up
    create_table 
: attachments ,: force  =>  true  do   | t |
      t
. string  : filename ,: default => ""
      t
. string  : content_type ,: defaut => ""
      t
. integer  : size ,: default => 0
      t
. string  : org_filename ,: default => ""

      t
. timestamps
    end
  end

  def self
. down
    drop_table 
: attachments
  end
end


model:

class  Attachment  <  ActiveRecord::Base
  has_attachment :content_type 
=>  [:image, ' application/pdf ' ' application/msword ' ' text/plain ' ],
    :max_size 
=>   4 .megabytes,  # 指定最大值
  :storage  =>  :file_system,   # 指定存储方式
  :path_prefix  =>   " /public/attachments/#{Time.now.year}/#{Time.now.month}/#{Time.now.day}/ "

  validates_as_attachment

end


view:

< form  name ="upload"  action ="/attachments/create"  method ="post"  ENCTYPE ="multipart/form-data"   >
  
<%   if  protect_against_forgery?  %>
    
< input  type ="hidden"  name ="authenticity_token"  value ="<%= form_authenticity_token %>"   >
  
<%   end   %>
  
< p >< input  name ="attach"  type ="file"   />
    
< input  id ="submit"  name ="submit"  type ="submit" value ="上传" />
  
</ p >
</ form >


controller:

def  create
    @attachment 
=  Attachment.new(:uploaded_data  => params[:attach])
    respond_to do 
| format |
      
if  @attachment.save!
        flash[:notice] 
=   ' Attachment was successfully created. '
        format.html { redirect_to(@attachment) }
        format.xml  { render :xml 
=>  @attachment, :status  =>  :created, :location  =>  @attachment }
      
else
        format.html { render :action 
=>   " new "  }
        format.xml  { render :xml 
=>  @attachment.errors, :status  =>  :unprocessable_entity }
      end
    end
  end

 

attachment使用起来很方便,但是其配置比较麻烦,主要是readme文档写的不够全面。所以就会出现一些奇怪的问题。

<1>问题1,其文件名莫名多了几级文件目录。如:/0000/0006/

#文件名

/ attachments / 2009 / 10 / 30 / 0000 / 0006 / Lighthouse.jpg


但是我并没有定义余下的目录“/0000/0006/”,这并不是我想要,为什么会出现呢?

 

原因:
一个目录下的文件是有限的,所以,作者采用了一种机制,使得文件分多个目录进行存储,在这里用到了id,如果id是integer,会自动将id拆分为两个,例如:id=9,则其存储即为:/0000/0009/。具体大家可以参照:attachment_fu/lib/attachment_fu/bakends/file_system_backend.rb文件full_filename即为文件存储的全路径,处理分区的方法即为:partitioned_path,上面有陈述,可以细细看看。

解决方法:

如果你不需要这种分目录的机制,

一种方法是重写full_filename,

一种就是直接在has_attachment里面加入:partition => false 验证即可。


现在的目录就可以完全操控了。

Attachment_fu will delete them automatically.

参照:http://9esuluciano.iteye.com/blog/137056

 

<2>在上传的时候,偶尔会出现一个验证错误:

Validation failed: Size  is   not  included  in  the list

 

c:/ruby/lib/ruby/gems/1.8/gems/activerecord-2.3.4/lib/active_record/validations.rb:1090:in `save_without_dirty!'
c:/ruby/lib/ruby/gems/1.8/gems/activerecord-2.3.4/lib/active_record/dirty.rb:87:in `save_without_transactions!'
c:/ruby/lib/ruby/gems/1.8/gems/activerecord-2.3.4/lib/active_record/transactions.rb:200:in `save!'
c:/ruby/lib/ruby/gems/1.8/gems/activerecord-2.3.4/lib/active_record/connection_adapters/abstract/database_statements.rb:136:in `transaction'
c:/ruby/lib/ruby/gems/1.8/gems/activerecord-2.3.4/lib/active_record/transactions.rb:182:in `transaction'
c:/ruby/lib/ruby/gems/1.8/gems/activerecord-2.3.4/lib/active_record/transactions.rb:200:in `save!'
c:/ruby/lib/ruby/gems/1.8/gems/activerecord-2.3.4/lib/active_record/transactions.rb:208:in `rollback_active_record_state!'
c:/ruby/lib/ruby/gems/1.8/gems/activerecord-2.3.4/lib/active_record/transactions.rb:200:in `save!'
D:/Project/RubyProjects/attachment_test/app/controllers/attachments_controller.rb:46:in `create'
D:/Project/RubyProjects/attachment_test/app/controllers/attachments_controller.rb:45:in `create'

原因与解决方案:

它models配置中的:min_size如果不设置位为0,在windows环境下,由于文件处理过程相对较长,所以取不到文件的大小,导致文件大小校验失败,只有把:min_size设为0,校验可以通过。

<3>文件重命名

在存储文件的时候,如果是中文名,经常出错,需要进行重命名。解决方案如下:

 

Code
  protected
  before_save :assign
  
#功能:重新命名、记录存储地址
  #流程:
  #1、记录原始文件名
  #2、重新命名
  #3、记录相对地址
  def assign
    self.org_filename 
= self.filename
    self.filename 
= Time.now.strftime('%Y%m%d-%H%M%S'+ "." + self.filename.split('.')[1]
    self.relative_url 
= self.public_filename
  end

 

<4>public_filename并非存储路径,public_filename是根据path_prefix和filename拼出来的。

如果指定的path_prefix的是固定的,public_filename就是文件的存储路径,

如果path_prefix是变量,就像我上面设置的随时间的改变而改变,那么public_filename就不能标识文件的存储路径,就需要定义一个新的字段来存储。

<5>如果上传中文名的文件,你会看到存储的文件名类似于“____.jpg”

原因:attachment_fu在对文件名进行了限制处理。

在attachment_fu.rb文件中有一个方法:

 

 
 
def sanitize_filename(filename) return unless filename returning filename . strip do | name | # NOTE: File.basename doesn't work right with Windows paths on Unix # get only the filename, not the whole path name . gsub ! /^.* ( \\|\/ ) /, '' # Finally, replace all non alphanumeric, underscore or periods with underscore name . gsub ! / [ ^ A - Za - z0 - 9 \.\- ] /, ' _ ' end end
解决方法:

 

如果为了记录中文

1、修改此方法,注释掉:name.gsub! /[^A-Za-z0-9\.\-]/, '_'

2、在上传直接记录原始文件名

 

 
 
@attachment = Attachment . new( : uploaded_data => params[ : attachment]) @attachment . org_filename = params[ : attachment] . original_filename
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值