我正在尝试使用multer支持将文件从我的React App客户端上传到我的节点/快速后端。
对于某些背景,我一直在使用邮递员6.7.2,节点8.11.1,表达4.16.3和multer 1.4.1。在学习了教程之后,我可以使用邮递员登录req.body并查看formdata中的条目。就像我可以在路由处理程序()中记录req.body和req.file一样,文件甚至保存。但是,当我尝试从我的react应用发送请求时,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());
}
reducers / admin / model.js
export const DoorsForm = new Record({
_id: '',
name: '',
material: '',
testImage: ''
});