【问题标题】:File upload requests all return 400 status codes文件上传请求全部返回400状态码
【发布时间】:2023-03-06 01:45:01
【问题描述】:

我正在尝试使用 Express 进行文件上传,但我发送的每个 multipart/form-data 请求都会收到 400 错误请求响应且没有错误。只是一个空的对象。我目前正在使用busboy-body-parser 解析多部分表单数据请求,但我也尝试过express-fileupload 并遇到了完全相同的问题。

这是我的请求方法:

get(endpoint) {
  return this.request('GET', endpoint, null);
}

post(endpoint, body) {
  return this.request('POST', endpoint, body);
}

postFile(endpoint, file) {
  return this.request('POST', endpoint, file, contentTypes.file);
}

async request(method, endpoint, body, contentType=contentTypes.json) {
  const { authToken } = this;
  const endpointUrl = this.getEndpointUrl(endpoint);
  const headers = new Headers();

  if(authToken) {
    headers.append(authTokenHeader, authToken);
  }
  headers.append('Accept', 'application/json, application/xml, text/plain, text/html, *.*');
  headers.append('Content-Type', contentType);

  const response = await fetch(endpointUrl, {
    method: method,
    headers: headers,
    body: this._serializeRequestBody(body, contentType),
  });

  const result = await this._parseResponse(response);

  if(!response.ok) {
    if(response.status === 401) {
      this.revokeAuth();
    }
    throw result || new Error('Unknown error (no error in server response)');
  } else if(result && result.authToken) {
    this.setAuthToken(result.authToken);
  }

  return result;
}

这里是_serializeRequestBody_parseResponse

_parseResponse(response) {
  const contentType = response.headers.get('Content-Type').split(';')[0];
  if(contentType === contentTypes.json) {
    return response.json();
  }
  return response.text();
}

_serializeRequestBody(body, contentType) {
  if(!body) return null;
  switch(contentType) {
    case contentTypes.json:
      return JSON.stringify(body);
    case contentTypes.file:
      const formData = new FormData();
      formData.append('file', body);
      return formData;
  }
  return body;
}

还有contentTypes:

const contentTypes = {
  json: 'application/json',
  file: 'multipart/form-data',
};

还有我的快递中间件:

if(this._expressLoggingMiddleware) {
  app.use(this._expressLoggingMiddleware);
}

if(this.isNotProductionEnv && this.isNotTestEnv) {
  app.use(require('morgan')('dev'));
}

// Adds `res.success` and `res.fail` utility methods.
app.use(require('./utils/envelopeMiddleware')());

// Allow cross-origin requests if `config.cors` is `true`.
if(config.cors) app.use(require('cors')());

// Parse JSON and form request bodies.
app.use(busboyBodyParser()); // parses multipart form data (used for file uploads)
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));

// Lookup users by the JWT in their request header.
app.use(passportJWTMiddleware(passport, this.jwtSecret, jwtPayload =>
  this.lookupUserfromAuthToken(jwtPayload).catch((error) => {
    log.warn('Error while looking up user from JWT:', error);
    return null;
  })
));

// Serve files from `config.publicDir`.
if(config.publicDir) {
  log.debug(`Hosting static files in "${config.publicDir}"`);
  app.use(express.static(config.publicDir));
}

这是 Chrome 开发工具中的请求信息

以及请求负载:

然后回应:

【问题讨论】:

    标签: javascript express file-upload multipartform-data


    【解决方案1】:

    答案最终是:不要手动将Content-Type 标头设置为multipart/form-data,因为如果您让浏览器为您执行此操作,它还会将所需的boundary 值附加到内容类型。

    所以为了修复我的代码,我只需要在发送 JSON 时明确设置 Content-Type 标头:

    if(contentType === contentTypes.json) headers.append('Content-Type', contentType);
    

    【讨论】:

      猜你喜欢
      • 2015-12-08
      • 1970-01-01
      • 2018-02-25
      • 2018-07-13
      • 1970-01-01
      • 2017-06-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多