天天看点

ThinkPHP---TP功能类之上传

【一】概论

(1)上传操作的核心操作:移动临时文件(move_upload_file),在thinkphp里封装了上传类upload.class.php

(2)上传类upload.class.php代码分析,位置thinkphp/library/think/upload.class.php

        ①上传配置信息

拓展:hash编码及应用

hash编码也叫sha1编码,为40位编码

由来:之前的md5编码为32位编码,在部分网站上已经可逆了。所以安全性上有缺陷,于是开发了更加安全的hash(sha1)编码。多了8位,所以在解码可逆步骤增加难度,自然也就更加安全

应用案例:qq的快传和网盘,php的原生方法sha1_file计算文件的sha1散列值,生成的值

                 qq快传和网盘快速上传文件的实现原理:

                                           ①扫描文件,生成文件编码。可能是sha1也可能是md5编码;

                                           ②拿到编码后去数据库找,看之前有没有记录。此时注意,只通过文件名是无法识别的,因为文件名可能有改动。所以只能通过md5编码或者sha1编码去找。若找到文件之前有记录,直接拿到记录文件名,然后将对方文件传上去。相当于复制一份发了过去,然后重命名文件。

因此今后欧判断文件是否一样,不能通过文件名来判断。而要通过文件结构来进行判断

      ②构造方法:可以在实例化时传递一个配置数组,然后在内部进行合并配置操作;

      ③geterror方法:获取最后一次的上传错误信息;

         语法:$upload->geterror();

         注意:因为该方法是上传类里的方法,所以应该由实例化的类去执行。而不是$this

      ④uploadone方法:上传单个文件,参数是$_files中的子元素,返回值是上传的结果。(成功返回具有9个元素一维数组,失败返回false)

      ⑤upload方法:参数通常是$_files整个数组,成功返回值是二维数组,失败返回false

仔细查看代码后可以发现uploadone方法其实也是调用了upload方法,完成单文件上传

      ⑥查看源码后发现上传错误,所以这里总结下上传错误0-7,注意没有5

     ⑦至于其他checksize(检查文件大小)、checkmime(检查文件mime类型)、checkext(检查文件后缀)等方法均为私有方法,只能在内部封装调用

总结:分析后得出公开的方法一共有4个---①构造方法实例化、②geterror返回错误、③uploadone上传单个文件、④upoad上传多个文件

【案例】实现公文里的附件上传

(1)注意:要满足以下几个条件

   ①表单属性必须有entype属性声明表单上传数据除了字符外,还含有二进制流数据---enctype="multipart/form-data"

   ②文件域type="file"

   ③提交方式必须是post

(2)修改add方法中的表单数据处理

为了符合mvc的设计规范,需要自定义一个模型,然后将文件上传和数据保存,在模型里封装一个方法。由这个方法执行数据的保存

(3)创建模型文件model.class.php

之所以创建模型是由于添加操作无法一步执行,因为需要对文件上传进行处理。而处理的部分最好不要放在控制器里,所以单独拿出来。

控制器里只负责接受数据和判断执行结果,具体的数据保存操作和处理有模型执行

(4)修改控制器方法,改为接收数据和判断执行结果。具体的数据保存造作放到模型里执行

        ①实例化自定义模型;②保存由模型处理

ThinkPHP---TP功能类之上传

(5)编写方法实现数据的保存

方法名:savedata

这里我先选择一张图片,点击上传,预览下输出的格式,浏览器输出如下(输出$_files['file'])

注意:

 1. 关于路径的说明

定义配置,配置上传路径

①如果地址是给服务器脚本使用的,则可以使用相对于入口文件的相对路径;也可以使用带盘符的绝对路径

②如果地址是给客户端用的,则地址应该写成"/",相对于站点域名后的地址

在上传的案例中整个路径都不会传递给服务器,则路径属于第一种情况。在上传时保存路径建议写成带盘符的形式

 2. 保存路径

ThinkPHP---TP功能类之上传

后期上传的文件都将保存在upload下,此时本地路径为c:\site\public\upload。但是这里要注意,要对路径进行拆分。因为后期项目上线,服务器的盘符和本地不一样,这时地址便会失效。所以必须对路径进行拆分,定义一个常量。

继续分析,上线后变得是前面的路径,即c:\site,而后面路径public\upload不会变。所以可以定义成两个常量,前面是工作路径,后面是固定路径。即使后期工作路径发送变化,也可以通过动态获取的方式获取到相关路径。通过魔术常量__dir__获取,表示获取当前工作目录。

所以可以拆分为

最后针对路径总结下:后期项目上线后即使使用绝对路径也可以动态获取

ThinkPHP---TP功能类之上传

 3. 常量定义:可以在入口文件定义常量

 (6)定义好常量后,输出检查

    因为uploadone方法上传单个文件,参数是$_files中的子元素,返回值是上传的结果(成功返回具有9个元素一维数组,失败返回false)

   如果成功,这里会返回一维数组

ThinkPHP---TP功能类之上传

(7)判断是否上传成功,并补全字段

拓展:

特别注意:保存上传路径时,数据表不可以写带盘符法人路径。因为上传的图片一般都要被浏览器使用。如果使用了带盘符的路径,那会导致http协议和file协议冲突

因为图片要展示给客户端,<img src='d:\www\itcast\1006\public\upload\17-01-02\01.jpg'/>,src肯定不能写成前面格式。绝对不可以把带盘符的地址输出到浏览器,因为服务器的协议是http协议,只有本地才可以用file协议

     ①静态资源路径没有盘符形式的,d:www\itcast\01\public\upload\16-10-01\01.jpg。纯前端访问可以以file:\\协议进行访问

     ②而且因为服务器的协议都是http协议,所以不能用盘符形式的路径

     ③只有本地才能用file协议

 最终代码:docmodel.class.php

本文总结:mvc心得->如果可以直接进行curd操作的,简单的基本操作可以直接在控制器编写。如果数据需要保存处理等操作,则最好放到模型里,进行数据的curd操作。

.