[/code]这两天做文件上传,碰到不少问题。把过程记录下来吧。
我没有用插件,自己照着《Ruby on Rails敏捷开发最佳实践》这本书上的例子写的。
数据库迁移文件:[code="java"]class CreatePeople < ActiveRecord::Migration
def self.up
create_table :people do |t|
t.column :name, :string
t.column :picture, :string
end
end
def self.down
drop_table :people
end
end
控制器:
class UploadController < ApplicationController
# before_filter:set_charset
# def set_charset
# response.headers["Content-Type"] = "text/html; charset=utf-8"
# end
def get
@person=Person.new
end
def create
@person=Person.new(params[:person])
if @person.save
if params[:person][:photo].size>0
@person.add_picture
end
flash[:notice]='成功'
redirect_to :action=>"show",:id=>@person
else
render :action=>'get'
end
end
def show
@person = Person.find(params[:id])
require 'iconv'
conv = Iconv.new("utf-8", "ISO-8859-1")
result = conv.iconv("/images/pictures/"+@person.picture)
result << conv.iconv(nil)
conv.close
@picture_path=result
end
end
model类:
class Person < ActiveRecord::Base
require 'iconv'
def make_file_name(name)
file_ex_name = name
return file_ex_name
end
def photo=(photo)
if photo.size>0 then
t=Time.now
#@name=params[:person][:name]
@content_size=photo.size
@file_data=photo.read
@filetype=photo.content_type
filename=photo.original_filename
#@filename_old=File.basename(filename).split(".")[0]
@filetype_suffix=File.basename(filename).split(".")[1]
#@new_filename=t.year.to_s+"-"+t.month.to_s+"-"+t.day.to_s+"."+@filetype_suffix
@new_filename=make_file_name(name.to_s)+"."+@filetype_suffix
end
end
def add_picture
if @file_data then
File.open(self.path_to_file(@new_filename),"wb") do |f|
f.write(@file_data)
self.update_attributes(:picture=>@new_filename)
end
end
end
def path_to_file(param_filename)
conv = Iconv.new("GBK","utf-8")
result = conv.iconv(RAILS_ROOT+"/public/images/pictures/"+param_filename)
result << conv.iconv(nil)
conv.close
return result
end
# def validate
# if @filetype!=nil
# errors.add("","只能上传图片")unless @filetype=~/^image/
# end
# if @content_size!=nil
# errors.add("","上传的图片大学不能炒股2MB") if @content_size>2*1024*1024
# end
# end
end
视图:
get.rhtml
<%=form_tag({:action=>'create',:id=>@person},:multipart=>true) %>
<%=error_messages_for'person'%>
<p><label for="person_name">用户名:</label>
<%=text_field :person,:name%></p><br/>
<p><label for="person_picture">图片</label><br/>
<%=file_field 'person','photo'%></p>
<%=submit_tag "创建"%>
show.rhtml:
<p>
<label for="person_name">姓名:</label>
<a href="<%=@picture_path %>" target="_blank">
<%= @person.name %></a>
</p>
<p>
<label for="person_picture">相片:</label>
<% if not @person.picture.empty? %>
<%= image_tag(@picture_path) %>
<% end %>
</p>
解释一下:我要用用户在表单中提交的name作为上传文件的文件名,这时会遇到编码的问题。一开始没有用iconv,结果name为中文的时候会出现无效字符的问题。因此我在make_file_name(name.to_s)name用to_s转换成字符串,后来发现有的中文可以,有的不可以,报错误参数。而且文件名是乱码。后来使用iconv,代码中需要注意的是:person.rb中conv = Iconv.new("GBK","utf-8")这一句,这样上传的文件名才不会是乱码。
另外一个问题就是model类中如何读取表单中的值。make_file_name(name.to_s)这样就可以,表单是<%=text_field :person,:name%>,用这里的属性name做参数就可以,原来还想着从控制器中读出,再穿过来,看来不用。