Angular 5 'Content-Type':'multipart/form-data' 重置为 'application/json'

Angular 5 'Content-Type': 'multipart/form-data' gets reset to 'application/json'

您好,我在尝试让我的 httpClient 补丁请求发送内容类型为 'multipart/form-data' 的 FormData 时遇到问题。

我已经指定了 headers 如图所示:

  private httpOptions = {
    headers: new HttpHeaders({
      'Content-Type': 'multipart/form-data', 'Cache-Control': 'no-cache', 'Pragma': 'no-cache'
    })
  };

然后我执行以下操作以保存到 nodejs 服务器:

const formData: FormData = new FormData();
formData.append('materialFile', 'something');
return this.httpClient.patch<any>(this.apiUrl  + loan.id, formData, this.httpOptions);

在我的 Nodejs/Express 服务器上,我执行以下操作:

const Multer  = require('multer');

router.patch('/:id', Multer().fields([{ name: "materialFile", maxCount: 1 }]), (req, res, next) => {
  console.log(req.files['materialFile']);
});

当我在浏览器上检查请求 headers 时,我看到 content-type 是 application/json。

有人知道为什么吗?

Angular尝试根据请求body自动设置httpheadercontent-type,完全不需要手动设置。如果 content-type header 在浏览器的开发工具中是 application/json,这意味着请求 body 已经更改,直到 angular 尝试定义 header。这种变化很可能发生在拦截器中。所以如果你有一个拦截器,对请求进行操作,问题可能就在那个时候。

正如 Hikmat G. 指出的那样,问题很可能源于 Http 拦截器,就我而言,我发现在我用来注入 JWT 令牌的授权拦截器中将内容类型设置为application/json如下图:

    return req.clone({
        setHeaders: {
        'Content-Type' :  'application/json',
        'Accept': 'application/json',
        'Authorization': `Bearer ${ token }`,
        },
    });

我确实需要这样,除了我发送文件作为 formdata 对象的一部分的特定请求,其中内容类型必须是 multipart/form-data,它会自动更改为json,所以我添加了一个条件来避免这个问题,它似乎有效:

        let json_blacklist = "/example/url";
        let reqHeaders = {
            setHeaders: {
            'Content-Type' :  'application/json',
            'Accept': 'application/json',
            'Authorization': `Bearer ${ token }`,
            },
        };

        if(req.url.includes(json_blacklist)) {
            delete reqHeaders.setHeaders["Content-Type"];
        }

        return req.clone(reqHeaders);

提示:对于发送文件的请求,不要将内容类型设置为 multipart/form-data,只需完全删除内容类型并允许浏览器自行设置内容类型,这将有助于防止 webkit 边界错误,因为浏览器会自动设置边界,请参阅 #40561738 了解更多详细信息。