在编写上传文件功能前需要先对PHP本地的配置文件(php.ini)进行基本的配置
file_uploads = On: 允许文件上传
max_execution_time = 30: php脚本最长执行时间
max_input_time = 60: php解析get/post输入数据的最长时间,从接收到执行php
post_max_size = 8M: 允许通过post上传数据的总大小(单位字节)
upload_tmp_dir = /Applications/MAMP/tmp/php: 系统默认的临时目录
upload_max_filesize = 32M: 允许的尽可能最大的文件上传大小(byte)
max_file_uploads = 20: 允许一个表单上同时上传的最多文件数量
以上配置页,可以用: phpinfo()查看
表单设置
form标签
method="POST": 表单请求类型必须是"POST"
enctype="multipart/form-data": 发送服务器之前如何对表单数据编码
input控件
<input type="file" name="user_file">:
<input type="hidden" name="MAX_FILE_SIZE" value="30000">
在隐藏中设置上传文件最大尺寸,php会检查该项,但该项会在前端轻易绕过,并不可靠
基本术语
临时目录: 基于对用户的不信任,上传文件必须先存储在服务器临时目录等待进一步处理
临时目录必须在php.ini配置文件中设置,用户可以修改
最终目录: 用户上传文件最终存储的目录,由用户自定义
3.4 $_FILE 变量
$_FILE: 超全局变量数组,保存着上传文件的全部信息
$_FILE: 是二维数组, $_FILE['key1']['keyw'] key1: <input type="file" name="key1">
key2: 上传文件的属性(5个) name: 文件原始名称(存储在用户本地电脑上时)
type: 文件MIME类型,由浏览器提供,php并不检查
size: 上传文件大小
tmp_name: 上传文件的临时文件名(存储在服务器上时)
error: 错误代码,也可以常量表示
相关函数
is_uploaded_file($tmp_name): 判断上传文件是否是通过POST上传的
move_uploaded_file($tmp_name, $destination):将文件移动到新位置
<?php
// 设置允许的文件类型
$allowed = ['image/jpeg','image/JPG','image/png'];
// 确保用户执行了上传操作,再执行以下代码
if (isset($_FILES['user_pic'])) {
// 上传的文件类型
$type = $_FILES['user_pic']['type'];
// 临时文件名
$tmpName = $_FILES['user_pic']['tmp_name'];
// 上传的原始文件名
$name = $_FILES['user_pic']['name'];
// 上传的图片地址
$imgFile = 'uploads/' . $name;
// 确保用户上传的类型是图片
if (in_array($type, $allowed)) {
if (move_uploaded_file($tmpName, 'uploads/'.$name)) {
// 如果上传成功,除返回提示信息外,还要返回文件名,用于在客户端预览图片
exit(json_encode(['status'=>1,'message'=>'上传成功','img_url'=>$imgFile]));
}
} else {
exit(json_encode(['status'=>0,'message'=>'类型错误']));
}
// 错误处理, 0 表示无错误,大于0即表示有错误,对于具体类型可以暂不作判断,感兴趣查阅手册
$error = $_FILES['user_pic']['error'];
if ($error > 0) {
exit(json_encode(['status'=>-1,'message'=>'上传失败']));
}
}
?>
<!--以上是前端页面部分-->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>异步文件上传</title>
</head>
<body>
<h3>上传用户头像</h3>
<!--因为是异步提交,通过js发送http请求,不再需要设置form属性-->
<p>选择头像:<input type="file" name="user_pic" id="user_pic"></p>
<p><button id="btn">上传</button><span id="tips"></span></p>
<script>
var btn = document.getElementById('btn');
btn.onclick = function () {
// 因为支持多文件上传,所以用files[0]获取第一个,其实就是单文件上传
var file = document.getElementById('user_pic').files[0];
// 通过FormData()对象获取用户提交的表单数据
var form = new FormData();
// append()可以将表单控制内容添加到对象属性中, 属性用name的值
form.append('user_pic', file);
// 创建Ajax请求对象
var request = new XMLHttpRequest();
// 监听请求过程, 设置成功回调
request.onreadystatechange = function () {
if (request.readyState === 4) {
// console.log(request.responseText);
// 解析服务器端返回的JSON数据
var data = JSON.parse(request.responseText);
// 获取占位符元素
var tips = document.getElementById('tips');
// 根据返回类型,确定应该执行的操作
switch (data.status) {
// 1: 表示上传成功,除提示信息外, 还要显示预览小图片
case 1:
tips.style.color = 'green';
tips.innerHTML = '<img src="'
+data['img_url']
+'" alt="用户头像" width="80">'
+data.message;
break;
// 对于0,1,可以集中处理,因为他们都是出错信息,样式也一样
case 0:
case -1:
tips.style.color = 'red';
tips.innerText = data.message;
break;
// 如果错误信息未在上述情形中,则认为是未知错误
default:
tips.innerText = '未知错误';
}
}
};
// 设置请求参数,直接提交到当前页面处理, true 表示异步,可以省略
request.open('post', '<?=$_SERVER['PHP_SELF']?>',true);
// 使用FormDate,不要设置请求头
// request.setRequestHeader('content-type','application/x-www-form-urlencoded');
// 将Ajax请求发送到服务器端指定php脚本处理,当前就是本页面
request.send(form);
}
</script>
</body>
</html>点击 "运行实例" 按钮查看在线实例
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号