在编写上传文件功能前需要先对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>
运行实例 »
点击 "运行实例" 按钮查看在线实例