我们已经知道了如何通过
ThinkPHP来完成表单提交和处理,那么如何在表单中增加
文件上传功能呢,通过ThinkPHP来添加文件上传功能非常简单,甚至不影响你的表单处理。
这其中用到的主要是文件上传类
UploadFile,使用ORG类库包中的Net.UpdateFile类,ThinkPHP内置的Action操作里面(主要是insert和update操作,其他操作可以相应实现)实现了自动识别是否存在文件上传,如果存在会自动进行处理。当然,是有前提的,就是必须按照ThinkPHP提供的附件数据结构。
内置的附件数据结构是一个单独的数据表,结构如下:
- CREATE TABLE `thinkphp_attach` (
- `
id` int(11) NOT NULL auto_increment,- `
name` varchar(255) NOT NULL,- `
type` varchar(255) default NULL,- `
size` varchar(20) NOT NULL,- `
extension` varchar(20) NOT NULL,- `
savepath` varchar(255) NOT NULL,- `
savename` varchar(255) NOT NULL,- `
module` varchar(100) NOT NULL,- `
recordId` int(11) NOT NULL,- `
userId` int(11) unsigned default NULL,- `
uploadTime` int(11) unsigned default NULL,- `
downCount` mediumint(9) unsigned default NULL,- `
hash` varchar(32) NOT NULL,-
PRIMARY KEY `id`- )
ENGINE=InnoDB DEFAULT CHARSET=utf8
也就是说,这个附件表可以承载任何模块的附件保存,根据module字段读取附件所在的模块,根据recordId字段决定该附件属于某一条记录。而不需要你在各自的数据表中添加任何附件
字段(当然,如果你的数据表有这个必要,可以自行添加),ThinkPHP读取附件的方式也很简单,寻找需要的模块(相当于某个数据表)的某个记录对应的附件即可,还可以获取某个用户的附件列表。
关于如何添加上传功能,可以参考
ThinkPHP文件上传类的使用这篇主题,里面已经清楚的描述了ThinkPHP的UploadFile类的使用,包括:
- 1、基本上传功能
- 2、批量上传
- 3、Ajax方式上传
- 4、自动生成图片缩略图
- 5、自定义参数上传
下面我们主要来讲下如何保存上传的附件数据以及读取附件列表。
如果你使用内置的insert方法或者update方法来实现表单提交和保存的话,只要数据结构和相关的类定义正确了,那么这个上传操作是自动的。
下面举个简单的例子:
我们来实现一个用户头像功能
首先来定义UserVo类
- class UserVo extends Vo{
- var
$id; // 用户编号-
var $name; // 用户账户-
var $nickname; // 用户昵称-
var $password; //登录密码-
var $registerTime; //注册时间-
var $status; // 用户状态-
var $email; // 用户邮箱}
假设我们需要对User表添加头像功能,就需要通过文件上传的方式来完成。但是我们在UserVo类里面并没有定义头像字段(User数据表中也没有定义头像字段)。头像(附件)数据我们通过另外一个数据表来统一保存。
- class AttachVo extends Vo{
- var
$id; //附件编号-
var $name; //原有名称-
var $type; //文件类型-
var $size; //文件大小-
var $extension; //扩展名-
var $savepath; //存放路径-
var $savename; //保存名称-
var $module; //模块名-
var $recordId; //记录编号-
var $uploadTime; //上传时间-
var $userId; //上传用户id-
var $hash; //附件的Hash值-
var $remark;- var
$downCount;- };
之所以需要定义这样一个类,是为了做到
系统的附件的通用性保存,里面记录了相关的附件数据和所关联的数据。
我们定义了一个UserAction类
- class UserAction extends Action{ }
定义了UserDao类
- class UserDao extends Dao{ }
由于使用了AttachVo类,我们还需要定义一个AttachDao类,尽管这个类其实什么也不做。
- class AttachDao extends Dao{ }
我们可以看到,ThinkPHP在
开发过程中,对于简单的
应用,其实仅仅是定义Vo类,Dao类和Action类可以什么方法都不用添加。
下面就要来添加表单模版,这个模版比之前的表单提交的例子就多了一个文件上传选择框,另外不要忘了添加
enctype="multipart/form-data",否则无法实现上传功能。
- <FORM METHOD=POST enctype="multipart/form-data" ACTION="__URL__/insert">
- <
TABLE>- <
TR>- <
TD align="right">用户名:</TD>- <
TD><INPUT TYPE="text" NAME="name"></TD>- </
TR>- <
TR>- <
TD align="right">密码:</TD>- <
TD><INPUT TYPE="password" name="password"></TD>- </
TR>- <
TR>- <
TD align="right">昵称:</TD>- <
TD><INPUT TYPE="text" NAME="nickname"></TD>- </
TR>- <
TR>- <
TD align="right">邮箱:</TD>- <
TD><INPUT TYPE="text" NAME="email"></TD>- </
TR>- <
TR>- <
TD align="right">头像:</TD>- <
TD><INPUT TYPE="file" name="photo" ></TD>- </
TR>- <
TR>- <
TD align="right"></TD>- <
TD><INPUT TYPE="submit" value="注册"></TD>- </
TR>- </
TABLE>- </
FORM>
注意,这里的头像input的name填写可以随意,只要不和其他input冲突就可以,除非你需要把该字段保存到自己的用户表中,完成后保存为index.html 文件名。目录结构这里就不再叙述了,QuickStart教程1里面已经描述的很清楚了,之后的
教程这方面就不再重复了。
因为我们使用了UserAction类,也就是使用User模块,所以,在这里,我们甚至可以不需要在Action类里面添加方法,直接使用内置的方法insert。
所以,到这里,用户的头像上传功能已经完成了,你不妨测试下,输入下面的URL地址:
http://localhost/Attach/index.php/User/index/
在某些情况下,可能不想用系统内置的上传实现,需要写自己的逻辑来添加更多的功能。这种情况适用于你有自己的附件保存方式的情况,下面来讲下如何自己重载附件上传的功能。
我们在UserAction类里面重载insert方法,
- function insert(){// 处理表单数据 参考前面的表单处理例子
- // 用快捷方式创建UserDao对象
$dao = D("User");// 根据表单提交创建UserVo对象$user = $dao->createVo();// 保存UserVo对象到数据库$result = $dao->add($user);- if (
$result){-
// 处理附件上传-
import("ORG.Net.UploadFile");-
// 定义文件上传类-
$upload = new UploadFile();-
// 执行文件上传操作-
$result = $upload->upload();- if(!
$result) {-
// 获取文件上传错误信息-
$this->error($upload->getErrorMsg());- }
-
// 如果上传成功,获取上传文件的信息-
$uploadList = $upload->getUploadFileInfo();-
// 对上传文件进行处理- // .........
- //
}- }
uploadList其实是一个VoList类,里面包含了多个AttachVo信息(如果上传多个文件的话)。
但是,通常情况下建议不要自己来重新上传处理方法,因为内置的上传处理方面考虑了很多因素和处理,是一个不错的选择,往往是对表单处理的要求比较复杂,这种情况下面建议用下面的方法。
- function insert(){
-
// 定义表单数据处理方法- // ..............
- // 如果表单数据保存成功
-
$id = $dao->add($vo);- if (
$id){-
// 调用系统上传处理方法-
$this->_upload($module,$id)-
// 这里的$module指需要保存的数据表(模块)名称- // $id 是之前表单保存成功的记录ID
- // 需要注意的是如果有在表单中添加_uploadFileTable参数话,这里的$module是无效的。
-
}- }