为了账号安全,请及时绑定邮箱和手机立即绑定

form表单设置enctype="multipart/form-data"后,电影保存Movie.js里save方法req.body.movie._id获取不到

multiparty比较复杂,我使用multer的话,由于body-parser只能解析json,不能解析文件,form表单设置enctype="multipart/form-data"后,req.body就获取不到我们要传的参数了,因为它不认识文件,express3.x就已经移除req.files了,那么使用中间件multer是否可以混合传参数和文件,如果不行,除了把文件上传单独放进一个form并设置enctype="multipart/form-data"外有什么办法

正在回答

2 回答

分析的很到位。。。。。。支持。。。。。

0 回复 有任何疑惑可以回复我~

为此写了篇文章,记录下,有问题的同学可以来讨论讨论:我的csdn博客

我们在路由里是这样处理的
router.post('/admin/movie/save',       User.signinRequired, User.permission, Movie.savePoster, Movie.save);

理想状态:

文件上传和文本域同属一个表单,并且表单设置enctype='multipart/form-data'

  1. 在savePoster里,获取上传的文件通过第三方中间件比如multer,multiparty等,req.file(s)可以获取到文件

  2. 在save中,获取表单中其他普通文本域的movie对象(包括movie[title], movie[director],movie[year]等等)可以通过body-parser的req.body.movie获取


我的情况:

在设置enctype='multipart/form-data'后,文件能正常接收,可以在multer中间件提供的方法中用req.file获取文件信息,打印req.file:

{ fieldname: 'uploadPoster',
      originalname: 'b922270259dece707ef6c6a50259a406_r.png',
      encoding: '7bit',
      mimetype: 'image/png',
      destination: 'public/uploads',
      filename: 'uploadPoster_1494237299545.png',
      path: 'public\\uploads\\uploadPoster_1494237299545.png',
      size: 134815 }


但是save里,req.body.movie._id获取不到了,提示:

Cannot read property 'id' of undefined

分析:

1.我们把事情弄简单点,不设置enctype='multipart/form-data',默认为application/x-www-form-urlencoded    描述:在发送前编码所有字符(默认)

点击提交按钮浏览器请求是这样的(通过Formdata):

http://img1.sycdn.imooc.com//591042ea00011eec04220389.jpg

savePoster方法里获取不到的req.file,因为表单已经被编码了所有字符,uploadPoster只是一个文件名,不是一个文件数据,save方法里正常获取movie对象(包括movie[title], movie[director],movie[year]等等);

2.设置enctype='multipart/form-data'

描述:不对字符编码,在使用包含文件上传控件的表单时,必须使用该值。

点击提交按钮浏览器请求是这样的:

http://img1.sycdn.imooc.com//591044910001bde604400850.jpg

这里普通文本域已经不被编码发送给后台了,后台savePoster中只能通过multer中间件提供的方法中用req.file获取文件,在save中通过req.body(我们要获取的是req.body.movie对吧,获取不到)获取不到。这里浏览器是通过Request.payload发送普通文本域表单数据,是由boundary拼接而成(这里又涉及到ff和chrome的差异了),总之我们用req.body指定是获取不到了,在java中倒是可以通过inputstream获取,这块我也不是很了解。

解决办法:

查了很多资料,终于自己想通了.  multer支持在获取文件数据同时获取表单域参数(果然看官方文档加上自己理解才是最好的)

multer官方文档: multer文件上传中间件官方文档 --npmjs

var express = require('express')
var multer  = require('multer')
var upload = multer({ dest: 'uploads/' })
var app = express()app.post('/profile', upload.single('avatar'), function (req, res, next) {  
// req.file 是 name为`avatar` 文件的信息
// req.body 将具有文本域数据, 如果存在的话})

在movie.js中

/*savePoster*/
	exports.savePoster = function(req, res, next) {
		var singleFileUpload=multer.single('uploadPoster');         //设置上传方式为单文件上传 	
		singleFileUpload(req, res, function(err){
			if (err) {
         	return  console.log(err);
    		} 
        	
    	    req.body = req.body;  //由于设置了enctype='multipart/form-data',我们在save方法里取req.body是取不到值的,这里使用multer的req.body能获取文本域的值,将multer里的req.body赋给当前的req.body,并next传给save方法
    	    console.log(req.file);
    	    next();
		});
  			
  			
		}

视频里面是直接在savePoster里配置multipart,我用的是multer,singleFileUpload=multer..是我引入的multer的配置文件,里面包括了multer中间件和设置好的参数(目录,文件大小限制等),所以我在这里可以直接用req.file获取接收到的文件(包括req.file.originalName等等).看代码里面的注释差不多解析清楚了。

exports.save = function(req, res) {
var movieObj = req.body.movie;
var id = movieObj._id;
...

结果:

成功在savePoster中获取req.file,在save中获取req.body.movie


后记:

我还**兮兮的问能不能分开上传,不放在一个表单里上传。好可耻。哦,对了,用formidable的同学可以尝试下,它也自带解析普通文本域的能力

var form = new formidable.IncomingForm();
form.parse(req, function(err, fields, files) {
    //do something with files or req.body(if its exists)
...

。。。慕课网不让说shabixixi,哈哈哈

2 回复 有任何疑惑可以回复我~

举报

0/150
提交
取消
node建站攻略(二期)——网站升级
  • 参与学习       51940    人
  • 解答问题       408    个

帮助你深入前后端开发留下的迷惑,为进一步自学打下基础

进入课程

form表单设置enctype="multipart/form-data"后,电影保存Movie.js里save方法req.body.movie._id获取不到

我要回答 关注问题
意见反馈 帮助中心 APP下载
官方微信