2.4 文件上传
本节介绍将本地的文件上传到服务器上的应用,掌握了这些和2.7节的“简单公开文件服务器文档”结合,就可以开发出高级的文件交换应用程序了。
本例要点
PHP中提供了文件上传的标准功能。当JSP/Servlet,CGI中实现文件的上传功能时,有的需要安装外部的库。而在PHP中完全没有这个必要,如同接受表单(form)数据或查询(query)信息一样,能够简单地实现文件上传。
这里,考虑到完成单个文件的上传可能太单调了,实现了多个文件上传的功能,同时加入了防止同名文件的重复保存的处理。
目录结构
Enctype属性是示意表单数据送信时的数据种类,当表单中定义了文件选择框(<input type="file">)时,请务必将其指定为“multipart/form-data”。
此处设定最大可上传的文件的容量(100万字节)。
需要注意的是,隐藏框的数据容易在客户端被删改。本例只是给大家参考一下,才这样做的,如果要万无一失地设置最大文件容量,建议使用php.ini的upload_max_filesize参数。
想将多个变量作为一个变量取得时,可以这样指定变量的名称,如“名称[]”,这样变量的值就会以数组的形式被赋值($_FILES['fl'][0]~[2])。
服务器上存在同名的情况,是否可覆盖旧文件的值会被用到,默认的值是“不可覆盖旧文件”。
$path是上传文件保存的目录路径,$num是保存发生错误的件数的变量。这里为了方便将文件保存目录放在服务器上的公开文件夹中,这在系统安全上是不合时宜的(例如恶意的第三者将PHP脚本也上传到同一目录下,就对服务器进行恶意的攻击了)。通常上传文件的保存目录必须放在未公开的目录下,而且,必须限制最低限的上传可能的文件类型。
前一页面指定的上传文件的内容,被保存在以下的变量中。表2-2所示的是name属性为[fl]时的例子,当然[fl]可以自由替换。
表2-2 name属性为[fl]时
这次,因为文件选择框的命名,$_FILES数组为三维的,只有像$_FILES['fl']['name'][0]~$_FILES['fl']['name'][2]这样才能存取。Sizeof函数是求数组$_FILES['fl']['name']的长度的。求出长度后,进行循环,一个一个文件地处理。
mb_convert_encoding函数是将文件的文字码从UTF-8转换到GB2312,如果服务器里使用了Fedora(Linux),请将GB2312换成UTF-8。
文件选择框空白时,跳到下一个处理。不能取得临时文件时,在$_FILES['fl']['tmp_name'][$i]中放置的为空字符串。
同名文件已经在服务器上存在,而且在“不可覆盖旧文件”被选择的情况下,不进行上传处理,只将变量$num加1。
is_uploaded_file函数对临时文件夹里保存的文件是否是浏览器上上传的文件进行验证,这是为了防止恶意的用户对文件进行不正当的操作。
is_uploaded_file函数返回False(与浏览器上上传的不是同一文件)时,如上面类似,只将变量$num加1。
在所有错误都没有发生的情况下,开始上传处理。显示上传文件信息,并利用move_uploaded_file函数将临时文件移动到服务器上的上传文件保存文件夹下。
另外,move_uploaded_file函数没进行文件移动时,临时文件夹中的文件会在脚本处理终了时被自动删除的。
$num的值大于0时,意味中存在上传失败的文件,将失败的文件数表示出来。
补充
执行时的注意事项
本节中用到的多字节函数(mb_~)是扩展函数。在第1章的环境设定中已经将多字节函数有效化了,这里不需要特别追加了。如果例子不能正常运行时,请检查服务器的设定。后面有用到多字节函数的地方都要注意这个问题。
上传时发生的错误号码
上传发生的错误号码可以通过超级全局变量$_FILES($_FILES['fl']['error'])取得,如表2-3所示。
表2-3 上传时的错误号码常量