Я пытаюсь использовать multer для поддержки загрузки файлов из моего клиента приложения реакции на мой узел / экспресс-бэкэнд.
Для некоторого фона я использовал почтальон 6.7.2, узел 8.11.1, экспресс 4.16.3 и мультитер 1.4.1. После обучения я мог использовать почтальон для входа в req.body и просмотра записей в форме данных; как я могу войти req.body и req.file в обработчик маршрута (), и файл даже сохраняет. Но когда я пытаюсь отправить запрос из моего приложения реагирования, req.body регистрируется как {}, а req.file регистрируется как неопределенное.
Это мой файл app.js.
if (process.env.NODE_ENV !== 'production') {
require('dotenv').config();
}
const path = require('path');
const port = process.env.PORT || 4000;
const mongoURI =
process.env.NODE_ENV !== 'production'
? 'mongodb://localhost/mern2'
: process.env.MONGODB_URI;
// node server dependencies
const express = require('express');
const bodyParser = require('body-parser');
const mongoose = require('mongoose');
const app = express();
const routes = require('./controllers/index');
// Server setup for MongoDB
mongoose.connect(mongoURI);
mongoose.set('useCreateIndex', true);
mongoose.Promise = global.Promise;
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
// use router handlers
app.use('/api', routes);
// error handler
app.use(function(err, req, res, next) {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
// render the error page
res.status(err.status || 500);
// res.render('error');
});
app.get("*", (req, res) => {
res.sendFile(path.join(__dirname, "client", "build", "index.html"));
});
app.listen(port, () =>
console.log('LISTENING FOR REQUESTS ON PORT ' + port)
);
это мой файл маршрутов (controllers / index.js)
const express = require('express')
, router = express.Router();
router.use('/admin', require('./admin'));
module.exports = router;
и это мой обработчик маршрута, (admin.js)
router.patch('/panel', upload.single('panelImage'), (req, res) => {
console.log('req.headers', req.headers);
console.log('req.body', req.body);
console.log('req.file', req.file);
res.send({message: 'success'});
});
на стороне реакции у меня есть функция patchFileReq, которая похожа на обычный запрос исправления, принимает, что добавляет заголовок данных составной формы и отправляет объект FormData в качестве тела.
backendUtils.js
export function patchFileReq (url, body, token) {
var formData = new FormData();
Object.keys(body).forEach((key) => {
if(body[key] instanceof File){
formData.append(key, body[key], body[key].name);
}
else {
formData.append(key, body[key]);
}
});
for (var key of formData.entries()) {
console.log(key[0] + ' ' + key[1]);
}
const headers = prepareFormDataHeaders(prepareAuthorizationHeaders(token));
return Observable.ajax.patch(url, formData, headers)
.map(parseAjaxResponse)
.catch(parseAjaxError);
}
вот вывод admin.js, когда я использую почтальон:
*** file *** { fieldname: 'testImage',
originalname: 'bsn_2R_80_test.png',
encoding: '7bit',
mimetype: 'image/png' }
req.headers { 'content-type': 'multipart/form-data; boundary=--------------------------069393334143100418462268',
'cache-control': 'no-cache',
'postman-token': 'd289023d-956e-4d03-a0b4-073e6ffbd346',
'user-agent': 'PostmanRuntime/7.6.0',
accept: '*/*',
host: 'localhost:4000',
'accept-encoding': 'gzip, deflate',
'content-length': '332255',
connection: 'keep-alive' }
req.body { testfield: 'testvalue' }
req.file { fieldname: 'testImage',
originalname: 'bsn_2R_80_test.png',
encoding: '7bit',
mimetype: 'image/png',
destination: './uploads',
filename: 'bsn_2R_80_test.png',
path: 'uploads/bsn_2R_80_test.png',
size: 331918 }
А вот вывод для admin.js, когда я использую свое приложение реакции
req.headers { 'x-forwarded-host': 'localhost:3000',
'x-forwarded-proto': 'http',
'x-forwarded-port': '3000',
'x-forwarded-for': '127.0.0.1',
'accept-language': 'en-US,en;q=0.9,pl-PL;q=0.8,pl;q=0.7',
'accept-encoding': 'gzip, deflate, br',
referer: 'http://localhost:3000/admin-panel/doors-and-sidelites',
accept: '*/*',
'content-type': 'multipart/form-data; boundary=--------------------------833495845447745121323852',
'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36',
'x-requested-with': 'XMLHttpRequest',
origin: 'http://localhost:4000',
authorization: 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjVjYzEzMGI5MmM2MjVmM2ZmMWRlNjk3OCIsImVtYWlsIjoiZ3JlZ29yeS50ZXJsZWNraUBnbWFpbC5jb20iLCJpYXQiOjE1NjIyNjc5MTgsImV4cCI6MTU2MjM1NDMxOH0.pb9GfYjiwQRK8TInsbhf1565ENnSBnsoELClLH1SXB0',
'content-length': '372484',
connection: 'close',
host: 'localhost:4000' }
req.body {}
req.file undefined
Чуть выше, где написано
req.body {}
req.file undefined
Где я не вижу того, чего ожидаю; Я ожидаю увидеть тот же результат для req.body и req.file, что и при использовании почтальона, который может каким-то образом взять тело и файл.
Редактировать: я добавляю больше кода переднего конца.
epics / admin.js это мое эпическое промежуточное ПО
...
import {adminSavePanelRequest} from '../../lib/backend;
const adminSavePanelSuccess = (payload) => ({payload, type: ADMIN_SAVE_PANEL_SUCCESS});
const adminSavePanelFailure = (payload) => ({payload, type: ADMIN_SAVE_PANEL_FAILURE});
const adminSavePanel = (action$, store) =>
action$.ofType(ADMIN_SAVE_PANEL)
.flatMap(() => {
const state = store.getState();
var serverPayload = {};
serverPayload = state.getIn(['adminPanel', 'doorsForm']).toJS();
return adminSavePanelRequest(serverPayload)
.map(adminSavePanelSuccess)
.catch((error) => Rx.Observable.of(error)
.do((error) => {
console.log(`Error: ${error}`);
})
.map(adminSavePanelFailure)
)
});
...
backend.js
import patchFileReq from './backendUtils';
export function adminSavePanelRequest(payload){
return patchFileReq('/api/admin/panel', payload, getAuthToken());
}
редукторы / админ / model.js
export const DoorsForm = new Record({
_id: '',
name: '',
material: '',
testImage: ''
});