表单提交
表单中的数据类型共两种:字符串型和文件型。
通过表单的enctype
属性告知浏览对请求数据做什么样的处理
例:
<form enctype="multipart/form-data" action="__URL__" method="POST">
<!-- MAX_FILE_SIZE 必须放在文件输入字段之前 -->
<input type="hidden" name="MAX_FILE_SIZE" value="30000" />
<!-- Name of input element determines name in $_FILES array -->
Send this file: <input name="userfile" type="file" />
<input type="submit" value="Send File" />
</form>
MAX_FILE_SIZE
隐藏字段(单位为字节)必须放在文件输入字段之前,其值为接收文件的最大尺寸。这是对浏览器的一个建议,PHP也会检查此项。在浏览器端可以简单绕过此设置,因此不要指望用此特性来阻挡大文件。实际上,PHP设置中的上传文件最大值是不会失效的。但是最好还是在表单中加上此项目,因为它可以避免用户在花时间等待上传大文件之后才发现文件过大上传失败的麻烦。
enctype值 | 作用 |
---|---|
application/x-www-form-urlencoded | 在发送前编码所有字符(默认)(空格转换为 “+” 加号,特殊符号转换为 ASCII 十六进制值) |
multipart/form-data | 不对字符编码。在使用包含文件上传控件的表单时,必须使用该值。 |
text/plain | 空格转换为 “+” 加号,但不对特殊字符编码。 |
要确保文件上传表单的属性是
enctype="multipart/form-data"
,否则文件上传不了。
全局变量 $_FILES
此数组包含有所有上传的文件信息。(假设文件上传字段的名称为 userfile。)
变量名称 | 值 |
---|---|
$_FILES['userfile']['name'] | 客户端机器文件的原名称。 |
$_FILES['userfile']['type'] | 文件的MIME 类型,例如image/gif |
$_FILES['userfile']['size'] | 已上传文件的大小,单位为字节。 |
$_FILES['userfile']['tmp_name'] | 文件被上传后在服务端储存的临时文件名。 |
$_FILES['userfile']['error'] | 和该文件上传相关的错误代码。 |
$_FILES['userfile']['error']
获取的值含义
error值 | 含义 |
---|---|
0 | 没有错误发生,文件上传成功。 |
1 | 上传的文件超过了 php.ini 中 upload_max_filesize 选项限制的值 |
2 | 上传文件的大小超过了 HTML 表单中 MAX_FILE_SIZE 选项指定的值。 |
3 | 文件只有部分被上传。 |
4 | 没有文件被上传 |
6 | 找不到临时文件夹。 |
7 | 文件写入失败。 |
文件被上传后,默认地会被储存到服务端的默认临时目录中,除非
php.ini
中的upload_tmp_dir
设置为其它的路径。
相关函数:
is_uploaded_file
— 判断文件是否是通过 HTTP POST 上传的
bool is_uploaded_file ( string $filename )
例:
<?php
if ( is_uploaded_file ( $_FILES [ 'userfile' ][ 'tmp_name' ])) {
echo "File " . $_FILES [ 'userfile' ][ 'name' ] . " uploaded successfully.\n" ;
echo "Displaying contents\n" ;
readfile ( $_FILES [ 'userfile' ][ 'tmp_name' ]);
} else {
echo "Possible file upload attack: " ;
echo "filename '" . $_FILES [ 'userfile' ][ 'tmp_name' ] . "'." ;
}
move_uploaded_file
— 将上传的文件移动到新位置
bool move_uploaded_file ( string $filename , string $destination )
例:
<?php
$uploads_dir = '/uploads' ;
foreach ( $_FILES [ "pictures" ][ "error" ] as $key => $error ) {
if ( $error == UPLOAD_ERR_OK ) {
$tmp_name = $_FILES [ "pictures" ][ "tmp_name" ][ $key ];
$name = $_FILES [ "pictures" ][ "name" ][ $key ];
move_uploaded_file ( $tmp_name , " $uploads_dir / $name " );
}
}
上传单个文件
例:
<?php
// In PHP versions earlier than 4.1.0, $HTTP_POST_FILES should be used instead
// of $_FILES.
$uploaddir = '/var/www/uploads/' ;
$uploadfile = $uploaddir . basename ( $_FILES [ 'userfile' ][ 'name' ]);
echo '<pre>' ;
if ( move_uploaded_file ( $_FILES [ 'userfile' ][ 'tmp_name' ], $uploadfile )) {
echo "File is valid, and was successfully uploaded.\n" ;
} else {
echo "Possible file upload attack!\n" ;
}
echo 'Here is some more debugging info:' ;
print_r ( $_FILES );
print "</pre>" ;
上传多个文件
例(html):
<form action="" method="post" enctype="multipart/form-data">
<p>Pictures:
<input type="file" name="pictures[]" />
<input type="file" name="pictures[]" />
<input type="file" name="pictures[]" />
<input type="submit" value="Send" />
</p>
</form>
例(php):
<?php
foreach ($_FILES["pictures"]["error"] as $key => $error) {
if ($error == UPLOAD_ERR_OK) {
$tmp_name = $_FILES["pictures"]["tmp_name"][$key];
$name = $_FILES["pictures"]["name"][$key];
move_uploaded_file($tmp_name, "data/$name");
}
}
接受上传文件的 PHP 脚本为了决定接下来要对该文件进行哪些操作,应该实现任何逻辑上必要的检查。
- 可以用
$_FILES['userfile']['size']
变量来排除过大或过小的文件 - 可以通过
$_FILES['userfile']['type']
变量来排除文件类型和某种标准不相符合的文件 - 可以通过
$_FILES['userfile']['error']
判断上传是否有错 - 可以通过
is_uploaded_file
判断是否上传非法文件
PHP 支持同时上传多个文件并将它们的信息自动以数组的形式组织。要完成这项功能,需要在 HTML 表单中对文件上传域使用和多选框与复选框相同的数组式提交语法。
注意:
MAX_FILE_SIZE
设置的值,不能大于ini
设置中upload_max_filesize
选项设置的值。其默认值为 2M 字节。- 如果内存限制设置被激活,可能需要将
memory_limit
设置的更大些,请确认memory_limit
的设置足够的大。 - 如果
max_execution_time
设置的值太小,脚本运行的时间可能会超过该设置。因此,也请保证max_execution_time
足够的大。
max_execution_time
仅仅只影响脚本本身运行的时间。任何其它花费在脚本运行之外的时间,诸如用函数system()
对系统的调用、sleep()
函数的使用、数据库查询、文件上传等,在计算脚本运行的最大时间时都不包括在内。
max_input_time
以秒为单位设定了脚本接收输入的最大时间,包括文件上传。对于较大或多个文件,或者用户的网速较慢时,可能会超过默认的60
秒。
- 如果 post_max_size 设置的值太小,则较大的文件会无法被上传。因此,请保证 post_max_size 的值足够的大。