【问题标题】:Fetch API and multer error while uploading file上传文件时获取 API 和 multer 错误
【发布时间】:2016-06-18 03:46:46
【问题描述】:

我正在尝试使用 fetch API 将文件上传到 node.js 服务器(如果与它有关,我正在使用 github 的 pollyfill:https://github.com/github/fetch)。

请求是这样完成的:

const data = new FormData();
data.append('file', file);
return fetch(this.concatToUrl(url), {
  method: 'post',
  headers: Object.assign({}, this.getHeaders(), {'Content-Type': 'multipart/form-data'}),
  body: data,
});

在我的服务器端,这个路由声明:

app.post('/media', upload.single('file'), mediaRoutes.postMedia);

并尝试像这样获取文件:

exports.postMedia = function(req, res) {
  console.log('req.file', req.file, req.files, req.body);
  return res.sendStatus(200);
}

但是req.file 没有被填充。

我也从快递方面收到此错误:

Error: Multipart: Boundary not found
[2]     at new Multipart (/Users/jmanzano/Development/web/test/node_modules/busboy/lib/types/multipart.js:58:11)
[2]     at Multipart (/Users/jmanzano/Development/web/test/node_modules/busboy/lib/types/multipart.js:26:12)
[2]     at Busboy.parseHeaders (/Users/jmanzano/Development/web/test/node_modules/busboy/lib/main.js:64:22)
[2]     at new Busboy (/Users/jmanzano/Development/web/test/node_modules/busboy/lib/main.js:21:10)
[2]     at multerMiddleware (/Users/jmanzano/Development/web/test/node_modules/multer/lib/make-middleware.js:32:16)
[2]     at Layer.handle [as handle_request] (/Users/jmanzano/Development/web/test/node_modules/express/lib/router/layer.js:95:5)
[2]     at next (/Users/jmanzano/Development/web/test/node_modules/express/lib/router/route.js:131:13)
[2]     at Route.dispatch (/Users/jmanzano/Development/web/test/node_modules/express/lib/router/route.js:112:3)
[2]     at Layer.handle [as handle_request] (/Users/jmanzano/Development/web/test/node_modules/express/lib/router/layer.js:95:5)
[2]     at /Users/jmanzano/Development/web/test/node_modules/express/lib/router/index.js:277:22
[2]     at Function.process_params (/Users/jmanzano/Development/web/test/node_modules/express/lib/router/index.js:330:12)
[2]     at next (/Users/jmanzano/Development/web/test/node_modules/express/lib/router/index.js:271:10)
[2]     at cors (/Users/jmanzano/Development/web/test/node_modules/cors/lib/index.js:178:7)
[2]     at /Users/jmanzano/Development/web/test/node_modules/cors/lib/index.js:228:17
[2]     at originCallback (/Users/jmanzano/Development/web/test/node_modules/cors/lib/index.js:217:15)
[2]     at /Users/jmanzano/Development/web/test/node_modules/cors/lib/index.js:222:13
[2]     at optionsCallback (/Users/jmanzano/Development/web/test/node_modules/cors/lib/index.js:203:9)
[2]     at /Users/jmanzano/Development/web/test/node_modules/cors/lib/index.js:208:7
[2]     at Layer.handle [as handle_request] (/Users/jmanzano/Development/web/test/node_modules/express/lib/router/layer.js:95:5)
[2]     at trim_prefix (/Users/jmanzano/Development/web/test/node_modules/express/lib/router/index.js:312:13)
[2]     at /Users/jmanzano/Development/web/test/node_modules/express/lib/router/index.js:280:7
[2]     at Function.process_params (/Users/jmanzano/Development/web/test/node_modules/express/lib/router/index.js:330:12)

这是通过中间件进行的配置:

app.use(bodyParser.urlencoded({extended: true}));
app.use(bodyParser.json());
app.use(expressValidator());
app.use(logger('dev'));
app.use(cookieParser());
app.use(methodOverride());
app.use(passport.initialize());
app.use(passport.session());
app.set('JWTSuperSecret', jwtConfig.secret);

if (process.env.NODE_ENV !== 'production') {
  app.use(cors());
}

此外,这可以与 POSTMAN 一起正常工作。所以,我认为我的请求有问题。

谢谢!

【问题讨论】:

    标签: node.js forms express multipartform-data


    【解决方案1】:

    无需指定标题{Content-Type': 'multipart/form-data'}:浏览器会替换它自己的标题。

    但是如果你暴露它,那么它在Request Headers 之前的content-type:multipart/form-data; boundary=... 之后没有指定boundary Request Payload 并且这会导致服务器端的错误。

    如果您打开浏览器控制台并看到标题,就会看到。

    所以,只是:

    fetch(this.concatToUrl(url), {
      method: 'post',
      body: data,
    });
    

    或者,如果您需要自定义标题,您可以像这样添加它们:

    var headers = Object.assign({},
                                {'content-type': 'application/json'},
                                this.getHeaders(), 
                                {'Content-Type': 'multipart/form-data'}
    );
    
       // Removal should be case insensitive, or in any case, the header will be included:
    
    
    Object.keys(headers)
          .forEach( function(k) { 
             if (k.toLowerCase()==='content-type') delete headers[k] 
          })
    
    const data = new FormData();
    data.append('file', file);
    return fetch(this.concatToUrl(url), {
      method: 'post',
      headers: headers,
      body: data,
    });
    

    【讨论】:

    • 这种方法的问题是我必须设置更多的自定义标头(例如允许 JWT 身份验证)。我怎样才能做到这一点?
    • 只需从标题列表中获得实力属性content-type。查看更新。
    【解决方案2】:

    对于那些在使用邮递员时遇到错误的人,请确保不要在标题中指定内容类型

    【讨论】:

      猜你喜欢
      • 2018-05-27
      • 2021-08-16
      • 2016-03-06
      • 1970-01-01
      • 1970-01-01
      • 2022-08-03
      • 2020-09-27
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多