发新话题
打印

ThinkPHP夜话之15:文件上传

ThinkPHP夜话之15:文件上传

ThinkPHP除了表单处理方面提供了非常方便的操作外,对于文件上传的处理也是非常的强大和方便。内置的文件上传类UploadFile类提供了下面的功能:
引用:
1、上传检测

2、多文件上传

3、自动生成上传图片缩略图

4、支持覆盖方式上传

5、支持上传类型、附件大小、上传路径定义

6、采用IFrame方式的Ajax上传机制支持

7、支持上传文件命名规则

8、支持对上传文件的Hash规则

9、可设置是否保存附件数据到数据库
在上传表单中可以进行很多参数的设置对上传进行灵活的定义,Action类的_upload方法会自动进行相关处理。
要更好的理解上传保存操作,可以参考ThinkPHP的附件数据表结构,更加详细下面的UploadFile类的参数和使用方法可以参考文件上传类的使用
努力为phpres做贡献
时刻准备着,当机会来临时你就成功了
打好基础,增加社会经验
资深技术工程师是我的梦想
承接各种团体网站外包服务和各种it技术培训
准备申请AJAX版大,希望大家支持~~

TOP

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是无效的。

}

}
努力为phpres做贡献
时刻准备着,当机会来临时你就成功了
打好基础,增加社会经验
资深技术工程师是我的梦想
承接各种团体网站外包服务和各种it技术培训
准备申请AJAX版大,希望大家支持~~

TOP

ThinkPHP文件上传类的使用
请参考:http://www.topthink.com.cn/index.php/Topic/id/21
努力为phpres做贡献
时刻准备着,当机会来临时你就成功了
打好基础,增加社会经验
资深技术工程师是我的梦想
承接各种团体网站外包服务和各种it技术培训
准备申请AJAX版大,希望大家支持~~

TOP

发新话题