发新话题
打印

ThinkPHP实例 - QuickStart系列教程3:文件上传

ThinkPHP实例 - QuickStart系列教程3:文件上传

我们已经知道了如何通过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是无效的。
  • }
  • }
神迹兄~~好久不见鸟~~~

TOP

发新话题