2016-03-04 2 views
7

Я пытаюсь использовать API-интерфейс fetch для загрузки файлов на сервер node.js (я использую glyub's pollyfill, если это что-то связано с ним: https://github.com/github/fetch).Fetch API и ошибка multer при загрузке файла

Запрос делается так:

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. Итак, я думаю, что я делаю что-то неправильно с запросом.

Спасибо!

ответ

3

Нет необходимости назначать заголовок {Content-Type': 'multipart/form-data'}: браузер заменяет свой собственный.

Но если вы подвергаете его, то он не указан boundary после content-type:multipart/form-data; boundary=... в Request Headers перед тем 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, 
}); 
+0

Проблема с этим подходом заключается в том, что я должен установить дополнительные пользовательские заголовки (например, разрешить JWT-аутентификацию). Как я могу это достичь? –

+1

Просто прославите свойство 'content-type' из списка заголовков. См. Обновление. –

8

Для тех, кто наткнуться на этот пост, которые имеют ошибку при использовании почтальона убедитесь, что в не указывается тип содержимого в заголовках.

+0

О, мой бог, спасибо –

Смежные вопросы