我们已经知道了如何通过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是无效的。
}
}