Nginx 1.19.0文件上传触发415错误,请求技术排查
解决Nginx上传模块+jQuery AJAX文件上传的415/400错误
问题分析
先理清楚为什么不同请求方式结果不一样:
- curl上传正常:因为curl会自动生成完整且正确的
multipart/form-data请求头(包含动态生成的boundary参数),Nginx上传模块能正确解析请求体。 - jQuery设置
contentType: false返回415:大概率是请求头或FormData构造有问题,导致Nginx无法识别请求的媒体类型。 - 强制设置
contentType: 'multipart/form-data'返回400:这个操作本身就有问题——multipart/form-data必须搭配boundary参数才能正确分割请求体中的字段,手动设置时没有这个动态生成的边界值,Nginx无法解析请求体,直接返回400。
解决方案
1. 修正FormData的构造(最常见原因)
确保你正确构造了FormData对象,没有遗漏文件字段或格式错误:
// 正确的FormData构造示例 var formData = new FormData(); // 绑定文件输入框的文件(假设输入框id为fileInput) formData.append('file', $('#fileInput')[0].files[0]); // 如果有其他表单字段(比如描述),也需要添加进去 formData.append('description', $('#description').val());
2. 调整jQuery AJAX配置并检查版本
- 去掉
async: false:同步请求会阻塞浏览器,且现代浏览器会发出警告,改为异步请求更合理。 - 确保使用较新版本的jQuery:旧版本(比如1.9以下)在处理
contentType: false和processData: false时可能存在bug,建议升级到3.x稳定版。 - 保持
contentType: false和processData: false不变,这两个选项是让浏览器自动处理请求头和表单数据的关键。
修正后的AJAX代码:
$.ajax({ url: '/upload', type: 'POST', data: formData, async: true, // 改为异步 cache: false, contentType: false, processData: false, success: function (response) { alert(response); }, error: function(xhr) { console.log('请求错误:', xhr.status, xhr.responseText); } });
3. 检查Nginx配置与日志
- 确认Nginx已正确加载上传模块:执行
nginx -V,查看输出中是否包含--with-http_upload_module(编译安装场景)或确认模块已通过动态加载方式启用。 - 查看Nginx错误日志(通常在
/var/log/nginx/error.log):415错误的详细原因会记录在这里,比如是否是Nginx拒绝了该文件的MIME类型。如果是,在location /upload块中添加upload_accept all;来允许所有类型的文件上传:location /upload { upload_pass @test; upload_store /tmp 1; upload_store_access user:r; upload_accept all; # 添加这一行允许所有文件类型 # 其他配置... } - 确保
/tmp目录及其子目录(0-9)的权限正确:Nginx进程的用户(通常是nginx或www-data)需要有写入权限,可执行chown -R nginx:nginx /tmp并确认权限为700左右。
4. 尝试原生XMLHttpRequest替代jQuery
如果上述方法都无效,可能是jQuery的AJAX封装有问题,改用原生XHR试试:
var xhr = new XMLHttpRequest(); xhr.open('POST', '/upload', true); xhr.onload = function() { if (xhr.status === 200) { alert(xhr.responseText); } else { alert(`上传失败,状态码:${xhr.status}`); } }; xhr.send(formData);
内容的提问来源于stack exchange,提问作者user12066
相关产品推荐
相关产品推荐

