如何使用 multer 或 body-parser 上传文件
Posted
技术标签:
【中文标题】如何使用 multer 或 body-parser 上传文件【英文标题】:How to upload file using multer or body-parser 【发布时间】:2016-07-12 04:29:20 【问题描述】:我是一名 NodeJS 初学者,正在阅读《使用 MongoDB 和 NodeJS 进行 Web 开发》一书。我被“multer”困在第6章。当我使用 multer 进行文件上传时,服务器会抛出以下错误:
/Users/fk / Documents / imageuploader / node_modules / express / lib / application.js: 209
throw new TypeError('app.use() requires middleware functions'); ^
TypeError: app.use() requires middleware functions
但是当我用 bodyParser 替换它时,服务器会启动,但是当我单击上传按钮时,它会在浏览器上显示以下错误。
500 TypeError: Cannot read property 'file' of undefined
但是,它应该将我重定向到显示上传文件的另一个页面。
这是我的 bodyParser 代码,请查看我是否正确使用它,因为它在服务器启动时给了我“body-parser deprecated”。我见过像我这样的其他问题,我也关注过,但它们都没有真正起作用。
app.use(bodyParser.json());
app.use(bodyParser.urlencoded(
extended: true
));
app.use(bodyParser(
uploadDir: path.join(__dirname, '../public/upload/temp')
));
以下代码显示了我如何使用 multer,以防万一有什么我不应该做的事情,请告诉我。在上传文件的情况下,body-parser 或 multer 哪个更好?
app.use(multer(
dest: path.join(__dirname, '../public/upload/temp')
));
var saveImage = function()
var possible = 'abcdefghijklmnopqrstuvwxyz0123456789',
imgUrl = '';
for (var i = 0; i < 6; i += 1)
imgUrl += possible.charAt(Math.floor(Math.random() * possible.length));
var tempPath = req.files.file.path,
ext = path.extname(req.files.file.name).toLowerCase(),
targetPath = path.resolve('./public/upload/' + imgUrl + ext);
if (ext === '.png' || ext === '.jpg' || ext === '.jpeg' || ext === '.gif')
fs.rename(tempPath, targetPath, function(err)
if (err) throw err;
res.redirect('/images/' + imgUrl);
);
else
fs.unlink(tempPath, function()
if (err) throw err;
res.json(500,
error: 'Only image files are allowed.'
);
);
;
saveImage();
前面的代码块是我用来上传文件的逻辑。在错误中,它在 saveImage 函数的以下行中将“文件”称为未定义。它无法获取路径,因此根据 saveImage 函数的 else 部分抛出错误 500。为什么“文件”在这里未定义?我不明白。
var tempPath = req.files.file.path,
【问题讨论】:
我在关注wiki.workassis.com/…这个例子 【参考方案1】:multer()
返回一个使用您指定的设置的中间件生成器,因此您不能将其返回值直接传递给app.use()
。您可以在documentation 中看到它可以生成的所有中间件类型,但通常生成的中间件是在路由级别添加的,而不是像其他正文解析器那样全局添加。这是因为您通常会传入您期望的文件字段的名称。
例如,这将接受表单字段名称为foo
的单个文件(以及任何非文件字段):
var upload = multer(
dest: path.join(__dirname, '../public/upload/temp')
);
// ...
app.post('/upload', upload.single('foo'), function(req, res)
if (req.file)
console.dir(req.file);
return res.end('Thank you for the file');
res.end('Missing file');
);
另外,body-parser
当前不导出支持multipart/form-data
的中间件,因此您不能使用该模块来处理上传的文件(好吧,没有以application/x-www-form-urlencoded
形式传递base64 编码的字符串或其他东西,但效率要低得多)。
【讨论】:
【参考方案2】:这是MEAN文件上传的基本代码,请检查
<form id="frmDoc" name="frmDocument" ng-submit="upload()" class="form-horizontal form-bordered" enctype="multipart/form-data" >
<fieldset>
<div class="form-group">
<label class="col-md-4 control-label" for="val_email">Document<span class="text-danger">*</span></label>
<div class="col-md-4">
<div class="input-group">
<input type="file" name="file" id='file' required="required" />
</div>
</div>
</div>
</fieldset>
<div class="form-group form-actions">
<div class="col-md-8 col-md-offset-4">
<button type="submit" class="btn btn-sm btn-primary"><i class="fa fa-upload"></i> submit</button>
</div>
</div>
</form>
客户端代码
app.controller ('myctrl',function($scope,$http)
$scope.upload = function ()
var file = angular.element(document.querySelector('#file')).prop("files")[0];
$scope.files = [];
$scope.files.push(file);
$http(
method: 'POST',
url: '/users/upload',
headers: 'Content-Type': undefined ,
transformRequest: function (data)
var formData = new FormData();
formData.append('model', angular.toJson(data.model));
formData.append('file', data.files[0]);
return formData;
,
data: model: title: 'hello', files: $scope.files
).success(function (res)
console.log(res)
);
);
服务器端代码
var multer = require('multer');
var mkdirp = require('mkdirp');
var storage = multer.diskStorage(
destination: function (req, file, cb)
//var code = JSON.parse(req.body.model).empCode;
var dest = 'public/uploads/';
mkdirp(dest, function (err)
if (err) cb(err, dest);
else cb(null, dest);
);
,
filename: function (req, file, cb)
cb(null, Date.now()+'-'+file.originalname);
);
var upload = multer( storage: storage );
router.post('/upload', upload.any(), function(req , res)
console.log(req.body);
res.send(req.files);
);
【讨论】:
嗨,如果我想发送多个文件,我需要对 $http 函数内的 angular transformRequest 函数进行哪些更改 循环遍历所有文件输入并将每个文件附加到 formData 上,如下所示。 for( 让 i=0 ; i使用 Multer 上传文件并将其保存到本地文件夹的代码
api- call fileUpload function
fileUpload(req)
.then(uploadRes =>
console.log('uploadRes', uploadRes)
)
.catch(err =>
console.log('err', err)
)
Create file upload service
const multer = require('multer') // import library
const moment = require('moment')
const q = require('q')
const _ = require('underscore')
const fs = require('fs')
let dir = './public'
/** Store file on local folder */
let storage = multer.diskStorage(
destination: function (req, file, cb)
cb(null, dir)
,
filename: function (req, file, cb)
let date = moment(moment.now()).format('YYYYMMDDHHMMSS')
cb(null, date + '_' + file.originalname.replace(/-/g, '_').replace(/ /g, '_'))
)
/** Upload files */
let upload = multer( storage: storage ).array('files')
/** Exports fileUpload function */
module.exports =
fileUpload: function (req)
let deferred = q.defer()
/** Create dir if not exist */
if (!fs.existsSync(dir))
fs.mkdirSync(dir)
console.log(`\n\n $dir dose not exist, hence created \n\n`)
upload(req, , function (err)
if (req && (_.isEmpty(req.files)))
deferred.resolve( status: 200, message: 'File not attached', data: [] )
else
if (err)
deferred.reject( status: 400, message: 'error', data: err )
else
deferred.resolve(
status: 200,
message: 'File attached',
filename: _.pluck(req.files,
'filename'),
data: req.files
)
)
return deferred.promise
【讨论】:
【参考方案4】:我将《Web Development with MongoDB and NodeJS》一书的代码更正如下:
app.use(multer(dest:path.join(__dirname,'../public/upload/temp')).any());
.
.
.
.
const tempPath = req.files[0].path, // Temporary location of uploaded file
ext = path.extname(req.files[0].originalname).toLowerCase(), // Get file extension of the uploaded file
targetPath = path.resolve(`./public/upload/$imgUrl$ ext`); // The final path for the image file
代码的其他部分保持不变。它有效,我可以上传图像文件。 最良好的祝愿, 迈赫达德·谢汗
【讨论】:
以上是关于如何使用 multer 或 body-parser 上传文件的主要内容,如果未能解决你的问题,请参考以下文章
如果我不上传文件,如何从npm的multer获取请求的正文?
Nodejs进阶:基于express+multer的文件上传