下面开始介绍使用Rails实现文件上传
从View开始:
我们要接受图片,使用的是<input type="file"...>这样的标签,但是注意,含有这样标签的form,在提交以后会产生一种叫做multipart/form-data 这样的POST message,所以我们需要设置一下<form>标签.
<%=start_form_tag ({:action=>"upload"},:multipart=>true )%>
<input type="file" name="file[file]">
<%=end_form_tag%>
自然你也可以使用helper method来输出 input 标签
进入Model:
这一部分是可以放在controller里面(技术上可以),但是MVC构架告诉我们,这样做是不合理的,因为我把保存文件到指定文件夹的工作交给Model(没有对应的表的model)
建立一个文件:file.rb放在Model下面
class MyFile < ActiveRecord::Base
def file=(file_field) # 这是有特殊含义的
File.open("#{RAILS_ROOT}/myfile", "wb+") do |f|
f.write(file_field.read)
end
end
end
上面的RAILS_ROOT表示Rails app的路径的常量,rails app自动产生的一个常数,file= 给Rails一个假想,让rails以为Files表中有一个file属性,这样,我们就可以传递一个以file为key的value过来,因为 Rails中update_attriubtes,save,new等,都可以使用一个hash作为argument.下面会见到如何使用.
另外重点说明wb+,我们不能使用w,比如用wb+,假如使用w上传图片会:
因为读取方式"w",破坏了二进制文件,我们使用"wb"(或者"wb+"),使用二进制模式(binary mode)打开文件,文件就不会遭到破坏
写Controller:
class UploadController < ApplicationController
def upload
unless request.get?
file = MyFile.new(params[:file]) # 自动调用 File 里面的file= method
if file.save
# 成功的操作
else
# 失败的操作
end
end
end
end
还需要更多:
前面说过,通过form可以发送一种特殊的POST message,叫做multipart/form-data,这时候,我们在提取<input type="file"...>中的内容时,它实际上一个从硬盘提取到内存的过程,这个过程把文件保存到了一个TempFile的类对象中 (object),TempFile在文档中描述是这样的 Class: Tempfile < DelegateClass(File),因此我们可以使用一些方法,来帮作我们更好的进行文件存储操作:
如上,我们通过params[:file][:file]得到的就说一个TempFile object,重要的method:
original_filename | 获得文件的名字 |
content_type | 得到文件的类型 |
read | 读取文件中的数据(从硬盘上读取到内存中) |
write | 写文件(把内存中数据写到硬盘中) |
length | 获取文件长度 |
在目前(今天是06-8-24)最新版本的RoR中,original_filename 形如: 17.gif 这很方便我们使用,假如要判断上传是不是图片就用 content_type, 结果的到形如: image/gif ,不论是什么格式的图片都是image/*** 那么可以在model中使用valide验证数据,这也是为什么把保存文件部分放入model中,因为model对数据可以进行有效的验证
转自:http://caoshouying.blog.163.com/blog/static/56948484201011753731772/