使用邮递员时,Multer会解析多部分表单数据,但不会在客户端应用的请求中解析多部分表单数据

时间:2019-07-04 19:30:10

标签: ajax reactjs express multer

我正在尝试使用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: ''
});

0 个答案:

没有答案