创建一个数据库(mysql):
use 库名;
drop table if exists records;
create table records
(
id int NOT NULL AUTO_INCREMENT,
name varchar(50) not null,
person MEDIUMBLOB not null,
PRIMARY KEY (id)
)ENGINE=InnoDB DEFAULT CHARSET=utf8
name用来存放上传文件的文件名。
person用来保存上传文件的二进制流。
MySQL数据库为BLOB做出的定义如下:BLOB数据类型是一种大型的二进制对象,可以保存可变数量的数据。BLOB具有四种类型,分别是TINYBLOB,BLOB, MEDIUMBLOB 和LONGBLOB,区别在于各自所能够保存的最大数据长度不同。
·tinyblob:仅255个字符
·blob:最大限制到65K字节
·mediumblob:限制到16M字节
·longblob:可达4GB
·blob:最大限制到65K字节
·mediumblob:限制到16M字节
·longblob:可达4GB
创建一个视图:
<%= start_form_tag ({:action => 'create'}, {"name" => "form1", :multipart => true}) %>
<input type='file'name='file'id='file'/><br>
<%= submit_tag '上传' %>
<%= end_form_tag %>
在start_form_tag标签中:multipart => true会产生在HTML的表单中加入enctype="multipart/form-data",multipart/form-data 能提高二进制文件的传输效率。表单标签中设置enctype="multipart/form-data"来确保匿名上载文件的正确编码
创建一个控制器:
class UploadController < ApplicationController
def create
sf = SaveFile.save(@params["file"]) if@params["file"]
end
def get_file
num = Record.find(:all,:order=>"id DESC")
send_data(num[0].person,:type=>"image/jpeg",:disposition=>"inline")
#send_data(num[0].person,:filename=>num[0].name)
end
end
create方法会调用SaveFile模型的save方法将文件的二进制流保存到数据库中。
get_file方法用于提供用户下载(如rar)或直接显示给拥护(如图象),其中:type的值需要按文件的类型而定,如jpg格式的图象是“image/jpeg”,rar则是使用默认的类型“application/object-stream”。
:disposition设置为inline表示直接显示数据,设置为attachment表示下载,默认为下载。
get_file的过程为从数据库中取得全部数据并按id号倒序排列并返回一个二维数组,数组[0]也就相当于最新插入的文件了。Person列存储的是该文件的二进制流。
创建一个模型:
class SaveFile < ActiveRecord::Base
def self.save(person)
file = person.read
name = person.original_filename
if file && name
Record.create(:name=>name,:person=>file)
end
end
end
save方法的person参数接受一个file对象,read方法取得该文件的二进制流,length得到上传文件的大小(单位b)用该方法可实现对上传文件大小的限制,original_filename获得文件名,content_type得到文件类型,local_path获得服务器上传文件存放的位置(在客户端文件上传时会将文件存放到服务器C盘下当前用户的Temp目录下如:C:/Documents and Settings/xuxiaolai/Local Settings/Temp)在该目录下文件名为CGI开头的就为上传的临时文件,所以用该方法取得的也是临时文件存放的目录,这些临时文件在随后的上传过程中会被自动清除。该模型用于存放文件到数据库。如需存放到服务器的磁盘中需更改至如下样式:
class SaveFile < ActiveRecord::Base
def self.save(person)
if person
File.open("pictures/#{person.original_filename]}", "wb") { |f| f.write(person.read) }
end
end
end
为了避免破坏二进制文件,必须调用File.open的二进制模式’wb’。