在 Express JS 中使用 Multer 根据扩展名过滤文件
Posted
技术标签:
【中文标题】在 Express JS 中使用 Multer 根据扩展名过滤文件【英文标题】:Filter files on the basis of extension using Multer in Express JS 【发布时间】:2016-12-03 19:38:53 【问题描述】:正如问题标题所解释的,我需要根据文件扩展名过滤上传的文件。所以,我浏览了官方文档并搜索了这个网站。
我的尝试
我已经尝试过遇到的解决方案。文件正在成功上传,但问题是如何过滤文件。目前我的 Router.js 文件如下所示。
Router.JS
var multer = require('multer');
var storage = multer.diskStorage( //multers disk storage settings
destination: function (req, file, cb)
cb(null, './public/uploads/')
,
limits:
files: 1,
fileSize: 1024 * 1024
,
filename: function (req, file, cb)
var datetimestamp = Date.now();
cb(null, file.fieldname + '-' + datetimestamp + '.' + file.originalname.split('.')[file.originalname.split('.').length -1])
,
onFileUploadStart: function(file)
console.log("Inside uploads");
if (file.mimetype == 'image/jpg' || file.mimetype == 'image/jpeg' || file.mimetype == 'image/png')
return true;
else
return false;
);
var upload = multer( //multer settings
storage: storage
).single('profilepic');
router.post('/profile', function(req, res)
upload(req,res,function(err)
if(err)
console.log(err);
else
console.log("Image was uploaded");
);
);
我尝试在 onFileUploadStart
中回显某些内容以检查它是否进入该函数。但事实并非如此。除了onFileUploadStart
,我还尝试了fileFilter
,正如link 中提到的那样,但它没有帮助。任何建议如何解决这个问题?提前致谢。
【问题讨论】:
请在 multer 问题中查看此评论。 github.com/expressjs/multer/issues/114#issuecomment-231591339 【参考方案1】:一个使用multer
的例子:
var storage = multer.diskStorage( //multers disk storage settings
destination: function (req, file, cb)
cb(null, './public/uploads/')
,
filename: function (req, file, cb)
var datetimestamp = Date.now();
cb(null, file.fieldname + '-' + datetimestamp + '.' + file.originalname.split('.')[file.originalname.split('.').length -1])
);
var upload = multer( //multer settings
storage: storage,
fileFilter: function (req, file, callback)
var ext = path.extname(file.originalname);
if(ext !== '.png' && ext !== '.jpg' && ext !== '.gif' && ext !== '.jpeg')
return callback(new Error('Only images are allowed'))
callback(null, true)
,
limits:
fileSize: 1024 * 1024
).single('profilepic');
摘自Node.js - File upload。原作者是Iceman 和Mikhail。归属细节可以在contributor page 上找到。该源在CC BY-SA 3.0 下获得许可,可以在Documentation archive 中找到。参考主题 ID:4080 和示例 ID:14210。
【讨论】:
var ext = path.extname(file.originalname);
你能定义path
吗
@KhaledRamadan 添加var path = require('path');
嗨,我对这个包 @AJ 有点陌生。我试图在上传之前验证我的 req.body,我将在哪里通过我的验证功能;如果失败,是否会向客户端发送错误响应?
@O'DaneBrissett 我认为该文件应该单独验证。您可以先验证req.body
中的所有输入,然后再进行文件验证。
更有效的方法是删除var ext = path.extname
行并添加RegExp
以检查例如。 const allowedExtensions = new RegExp(/.(jpg|png|jpeg)$/gi)
和测试【参考方案2】:
这很有帮助,谢谢。在我的例子中,我需要添加一个中间件来确保 JWToken 就位并使用 XHR 构建它。如果其他人需要这方面的帮助,这对我有用。在 XHR 标头中传递令牌时可以轻松完成。
客户:
const loadHandler = event =>
// loadHandler mandate
const errorHandler = event =>
// error mandate
const abortHandler = event =>
// abort mandate
const data = new FormData()
data.append('file', upFile)
var formData = new FormData();
var xhr = new window.XMLHttpRequest();
formData.append('files', upFile); // this is a state object set onChange
xhr.open('post', '/uploadFile', true);
xhr.setRequestHeader('token', thetoken); // Passing token in header
xhr.addEventListener("load", loadHandler, false);
xhr.addEventListener("error", errorHandler, false);
xhr.addEventListener("abort", abortHandler, false);
xhr.send(formData);
服务器
const express = require('express'),
app= express.Router(),
rf = require('./RoutFuctions');
...
app.post('/uploadFile', rf.verifyToken, function (req, res, next)
// upload portion above
);
RoutFunctions.js
const jwt = require('jsonwebtoken')
const tokenTest = (token, res, jwt, caller, next) =>
jwt.verify(token, process.env.SECRET_KEY, err =>
if(err)
res.sendStatus(403);
console.log('could not verify token');
else
console.log("token verified");
next(); // Next middleware
);
exports.verifyToken = function(req, res, next)
if(req.body.token !== undefined) // non upload scenario
var caller = ''
if(req.body.caller !== undefined) caller = req.body.caller;
tokenTest(req.body.token, res, jwt, caller, next)
else // attempt to extract token in XHR header upload scenario
if(req.headers.token !== undefined)
var token = req.headers.token
tokenTest(req.headers.token, res, jwt, caller, next)
else
res.sendStatus(403);
【讨论】:
【参考方案3】:多个或单个文件的完整实现。
注意:对于单个文件,请使用 .single('filename') 或 .array('filename',1)
const express = require("express");
const app = express();
var session = require('express-session')
const multer = require("multer");
const path = require("path");
var storage = multer.diskStorage( //multers disk storage settings
destination: function (req, file, cb)
cb(null, path.join(__dirname,"uploads"))
,
filename: function (req, file, cb)
var datetimestamp = Date.now();
cb(null, file.fieldname + '-' + datetimestamp + '.' + file.originalname.split('.')[file.originalname.split('.').length -1])
);
var upload = multer( //multer settings
storage: storage,
fileFilter: function (req, file, callback)
var ext = path.extname(file.originalname);
if(ext !== '.png' && ext !== '.jpg' && ext !== '.gif' && ext !== '.jpeg')
return callback(new Error('Only images are allowed'))
callback(null, true)
,
limits:
fileSize: 1024 * 1024
).array('profile',2);
app.post("/upload", upload,(req, res) =>
res.json(
msg:"uploaded"
)
);
app.use((err,req,res,next)=>
console.log(err.message);
res.status(404).json(
msg:err.message
)
)
app.listen(
8080,
(error) =>
if (error)
console.log("error");
,
() =>
console.log("listening at port 8080");
);
注意:您可以通过扩展 Error 来创建自己的自定义错误消息,并在 err,req,res,next 块中发送自定义消息和状态
【讨论】:
【参考方案4】:我现在正在测试这个替代方案。对我来说似乎可行,但我仍在评估( 用打字稿):
import crypto from 'crypto';
import multer, FileFilterCallback from 'multer';
import resolve from 'path';
const tmpFolder = resolve(__dirname, '..', '..', 'tmp');
const fileSize = 50 * 1024 * 1024;
export default
tmpFolder,
fileFilter: (
request: Express.Request,
file: Express.Multer.File,
callback: FileFilterCallback,
) =>
const acceptedTypes = file.mimetype.split('/');
if (acceptedTypes[0] === 'image' || acceptedTypes[0] === 'video')
callback(null, true);
else
callback(null, false);
callback(new Error('Only images and videos formats allowed!'));
,
limits:
fileSize,
,
storage: multer.diskStorage(
destination: tmpFolder,
filename: (request, file, callback) =>
const fileHash = crypto.randomBytes(16).toString('hex');
const fileName = `$fileHash-$file.originalname`;
return callback(null, fileName);
,
),
;
【讨论】:
【参考方案5】:如果你习惯web开发,可以在前端验证,不传到后端,可以试试:
var file = files[0];
var imageType = /image.*/;
if (!file.type.match(imageType))
// do something
【讨论】:
请注意,您的脚本仍然可以在浏览器控制台的源文件中进行操作。所以永远不要只依赖前端验证 你永远不应该依赖前端验证,这是 100% 正确的,但你应该ALSO
做前端验证,并不是所有的用户都是可以更改源代码的开发人员,其中一些人只是愚蠢和客户端验证将节省一些流量以上是关于在 Express JS 中使用 Multer 根据扩展名过滤文件的主要内容,如果未能解决你的问题,请参考以下文章
无法使用 express 和 multer 运行 node.js 服务器以在节点中上传文件
在 Express Node js 中使用 multer sftp 将文件上传到远程服务器?