如何用Ajax发送超过1MB的文件?PHP上传异常问题排查
首先,先明确你遇到的error => [0] => 3对应的是PHP的UPLOAD_ERR_PARTIAL常量,意思是文件只有部分被上传完成。虽然你已经在php.ini里放开了上传大小限制,但还有几个常见的地方可能导致这个问题,咱们一步步排查:
1. 确认php.ini的设置是否真正生效
有时候我们修改了php.ini,但要么改了错误的配置文件,要么没重启web服务器导致设置没生效。你可以在upload.php里添加一行代码:
phpinfo();
访问这个页面后,搜索upload_max_filesize、post_max_size、max_input_time这几个参数,看它们的实际值是不是和你设置的一致。如果不一致,找到正确的php.ini文件(可以通过phpinfo里的Loaded Configuration File字段查看)修改后,重启Apache/Nginx和PHP-FPM(如果用的话)。
2. 检查Web服务器的上传大小限制
php.ini的设置只是一部分,Web服务器本身也有自己的文件大小限制:
- 如果你用的是Apache:
打开Apache的配置文件(比如httpd.conf或者站点的虚拟主机配置),查找LimitRequestBody指令。如果它被设置成了小于1MB的数值(比如1048576),就会截断大文件。把它改成LimitRequestBody 0(0表示无限制),然后重启Apache。 - 如果你用的是Nginx:
打开Nginx的配置文件(nginx.conf或者站点的配置文件),查找client_max_body_size指令。默认情况下这个值通常是1MB,你需要把它改成和php.ini匹配的大小,比如client_max_body_size 2G;,然后重启Nginx。
3. 给Ajax请求添加超时处理
大文件上传需要更长的时间,虽然你设置了PHP的max_input_time和max_execution_time,但XMLHttpRequest本身也可能因为超时中断上传。你可以在Ajax代码里添加超时设置:
let formData = new FormData(); for (let i = 0; i < fileInput.files.length; i++) { formData.append('files[]', fileInput.files[i], fileInput.files[i].name); } let xhr = new XMLHttpRequest(); xhr.open('POST', '../upload.php', true); // 设置超时时间为5分钟(300000毫秒) xhr.timeout = 300000; // 监听超时事件,方便排查问题 xhr.ontimeout = function() { console.error('上传超时,请检查网络或调整超时设置'); }; xhr.send(formData);
4. 排查中间件或安全软件的拦截
如果你的服务器前面有CDN、防火墙,或者安装了类似ModSecurity的安全模块,它们可能会拦截大文件上传。你可以暂时关闭这类工具测试一下,或者在它们的配置里放开文件大小限制。
最后补充一句:你的Ajax代码本身是没问题的,FormData的使用和xhr的发送都符合规范,所以问题大概率出在服务器端的配置上。
内容的提问来源于stack exchange,提问作者Shuvo Mohajan

