首页 > 解决方案 > nginx 1.19.0:上传文件时出现 415 错误

问题描述

我正在使用 nginx 提供一个页面,该页面包含一个用于将文件上传到服务器的表单。我在 POST 请求中使用 FormData() 类作为我的数据:

js:

$.ajax({
   url: /upload,
   type: 'POST',
   data: formData,
   async: false,
   cache: false,
   contentType: false,
   enctype: 'multipart/form-data',
   processData: false,
   success: function (response) {
     alert(response);
   }
});

我正在使用示例 nginx 上传模块,使用此页面底部的默认配置:https ://www.nginx.com/resources/wiki/modules/upload/ :

location /upload {
    # Pass altered request body to this location
    upload_pass   @test;

    # Store files to this directory
    # The directory is hashed, subdirectories 0 1 2 3 4 5 6 7 8 9 should exist
    upload_store /tmp 1;

    # Allow uploaded files to be read only by user
    upload_store_access user:r;

    # Set specified fields in request body
    upload_set_form_field $upload_field_name.name "$upload_file_name";
    upload_set_form_field $upload_field_name.content_type "$upload_content_type";
    upload_set_form_field $upload_field_name.path "$upload_tmp_path";

    # Inform backend about hash and size of a file
    upload_aggregate_form_field "$upload_field_name.md5" "$upload_file_md5";
    upload_aggregate_form_field "$upload_field_name.size" "$upload_file_size";

    upload_pass_form_field "^submit$|^description$";

    upload_cleanup 400 404 499 500-505;
}

# Pass altered request body to a backend
location @test {
    proxy_pass   http://localhost:8080;
}

我没有使用任何 PHP 脚本或其他任何东西;我的印象是默认的上传模块配置只会将上传的文件转储到 /tmp/1(我已经创建了这个目录并授予了 nginx 的写权限)。该文件只有几 kb,因此文件大小应该没有问题。

当我尝试上传文件时,我收到 HTTP 415 错误,即不支持的媒体类型。我上传的文件有一个扩展名 .bin,这是 /etc/nginx/mime.types 文件中支持的 MIME 类型。

我可以使用 cURL 在命令行上发出类似的请求:

curl -F 'file@=myfile.bin' http://<URL>/upload

这很好用。检查 curl 的输出,我在 POST 标头中看到了

Content-Type: multipart/form-data; boundary=-------etc

但这在上面的 jQuery ajax 调用中被禁用为

Content-Type: false;

正如 SO 帖子中所建议的那样,我如何异步上传文件?. 如果我在对 multipart/form-data 的 ajax 调用中强制使用 Content-Type,则会收到 400 Bad Request 错误。有人可以解释我要去哪里错了吗?

标签: javascriptjqueryajaxnginx

解决方案


所以似乎当使用 FormData 类发布表单数据时,jquery ajax POST 方法将通过

Content-Type: false

对后端服务器的权限,在本例中为 nginx。nginx 无法识别此内容类型,因此出现 415 错误。我找不到解决这个问题的直接答案,所以我不得不求助于一个简单的 XMLHTTPRequest:

var form = document.getElementById("MyFormId");

var req = new XMLHTTPRequest();
req.open('POST', url, true);

req.onprogress = function () {
    // handle progress
}

req.onload = function () {
    // successful request
}

req.onerror= function () {
    // request in error
}

req.send(new FormData(form));
event.preventDefault();

当我发送这个时,表单数据会原封不动地进入 nginx 并在 HTTP 请求中

Content-Type: 'multipart/form-data'

就像我看到的使用 cURL 一样。

我希望这对某人有用。


推荐阅读