上传文件

程序中一个常见的任务是上传某种文件,可以是用户的照片,或者 CSV 文件包含要处理的数据。处理文件上传功能时有一点要特别注意,表单的编码必须设为 "multipart/form-data"。如果使用 form_for 生成上传文件的表单,Rails 会自动加入这个编码。如果使用 form_tag 就得自己设置,如下例所示。

下面这两个表单都能用于上传文件:

<%= form_tag({action: :upload }, multipart: true ) do %>
   <%= file_field_tag 'picture' %>
<% end %>
 
<%= form_for @person do |f| %>
   <%= f.file_field :picture %>
<% end %>

像往常一样,Rails 提供了两种帮助方法:独立的 file_field_tag 方法和处理模型的 file_field 方法。这两个方法和其他帮助方法唯一的区别是不能为文件选择框指定默认值,因为这样做没有意义。正如你所期望的,file_field_tag 方法上传的文件在 params[:picture]中,file_field 方法上传的文件在 params[:person][:picture] 中。

5.1 上传了什么

存在 params Hash 中的对象其实是 IO 的子类,根据文件大小,可能是 StringIO 或者是存储在临时文件中的 File 实例。不管是哪个类,这个对象都有 original_filename 属性,其值为文件在用户电脑中的文件名;还有个 content_type 属性,其值为上传文件的 MIME 类型。下面这段代码把上传的文件保存在 #{Rails.root}/public/uploads 文件夹中,文件名和原始文件名一样(假设使用前面的表单上传)。

def upload
   uploaded_io = params[ :person ][ :picture ]
   File .open(Rails.root.join( 'public' , 'uploads' , uploaded_io.original_filename), 'wb' ) do |file|
     file.write(uploaded_io.read)
   end
end

文件上传完毕后可以做很多操作,例如把文件存储在某个地方(服务器的硬盘,Amazon S3 等);把文件和模型关联起来;缩放图片,生成缩略图。这些复杂的操作已经超出了本文范畴。有很多代码库可以协助完成这些操作,其中两个广为人知的是 CarrierWave 和 Paperclip

如果用户没有选择文件,相应的参数为空字符串。

5.2 使用 Ajax 上传文件

异步上传文件和其他类型的表单不一样,仅在 form_for 方法中加入 remote: true 选项是不够的。在 Ajax 表单中,使用浏览器中的 JavaScript 进行序列化,但是 JavaScript 无法读取硬盘中的文件,因此文件无法上传。常见的解决方法是使用一个隐藏的 iframe 作为表单提交的目标。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值