//生成multiparty对象,并配置上传目标路径
var form = new multiparty.Form({uploadDir: (mainPath + '/picTemp/')});
我们生成multiparty对象后,就可以使用multiparty.from().parse(req, callback)进行文件上传。文件上传成功实际上就会上传到我们刚才定义的上传目录中,然后返回files。我们可以看下文件上传效果:
//查看图片是否超过限制
var picNum = 0;
par.picNames = Object.keys(files);
var picSizeArr = [];
for(var picKey in files){
if(files[picKey].length > 1){//每个名字只能带一张图片
delPicsWithFiles(files);
return cb('文件参数有误', 400);
}
par[picKey] = files[picKey][0].path;
picNum += files[picKey].length;
picSizeArr.push(parseInt(files[picKey][0].size));
}
//根据上传来的files表单删除图片
function delPicsWithFiles(files) {
//图片超过限制,删除上传来的图片
for (var key in files) {
files[key].forEach(function (picObj) {
var uploadedPath = picObj.path;
fs.unlink(uploadedPath, function () {
});
});
}
}
第一步校验通过了,下一步就是针对图片和非图片做不同的操作。图片允许多图同时上传,所以我们需要判断上传的图片是否超过我们限制的最大张数,如果图片张数超限,则删除所有已上传图片:
if(picNum > maxPic){
//图片超过限制,删除上传来的图片
delPicsWithFiles(files);
return cb('图片个数超过限制', 400);
}
并且需要判断图片文件大小是否符合规范,一般大小要和服务器配置一致,防止文件大小超过服务器限制大小。
if(picSizeArr[0] > 4000000) {
delPicsWithFiles(files);
return cb('图片过大,请重新选图!',400);
}
//检验参数是否正确,包括图片命名,不正确的话去删除上传的图片,并且返回错误
checkParFunc(par,function (err,errCode) {
if(!err){//验证正确,去重命名
par.files = files;
picHelp.renamePics(par,pathDir,isNeedUid,function (err,errCode,param) {
if(err){
cb(err, errCode, param);
delPicsWithFiles(files);
return;
}
cb(null, 0, param);
});
return;
}
//验证不正确,删除上传来的图片
delPicsWithFiles(files);
cb(err,errCode);
});
function checkParFunc(par, cb) {
if (!par.banner1 || !par.shopTitle1 || !par.price1 || !par.score1 || !par.linkUrl1) {
return cb('参数不全', 400);
}
cb(null, 0, par);
}
如果到这里检验通过一般来说我们图片上传业务逻辑没问题了。但是我们还是可以继续优化,刚才上传成功的截图我们可以看到文件上传后文件名都是随机字符串,我们很多时候都是需要对文件上传做分类才可以维护数据。所以下一步我们通过分割时间戳按照时间来将上传的图片转移到新的文件夹存储,并且我们移动到真正存储的文件夹时,通过fs.readFile()取到文件后缀名,然后将文件重命名成按时间戳进行命名,最终移动文件夹返回文件所在的地址,文件上传逻辑大功告成:
//给上传的图片重命名 //par:参数 picType:路径名
picHelp.renamePics = function (par,picType,isNeedUid,cb) {
if(!par.files){
cb('参数有误',400);
return;
}
//构造路径
var uid = 0;
if(par.userInfo){
uid = par.userInfo.main_userInfo ? par.userInfo.main_userInfo.uid : par.userInfo.uid;
}
var date = new Date();
var userPath = '/' + picType;
userPath += '/' + date.getFullYear();
userPath += '/' + (date.getMonth()+1);
userPath += '/' + date.getDate();
if(isNeedUid == true) {
userPath += '/' + parseInt(uid / 100);
userPath += '/' + uid;
}
mkdirs((mainPath + userPath),function (err) {//创建目录
if(err){
cb(err,400);
return;
}
userPath += '/' + date.getHours() + date.getMinutes() + date.getSeconds() + date.getMilliseconds();
changeDir(par, 0, userPath, function (err, par) {
if (err) {
cb(err, 400,par);
return;
}
cb(null, 0, par);
});
});
}
//递归创建目录 异步方法
function mkdirs(dirname, callback) {
fs.exists(dirname, function (exists) {
if (exists) {
callback(null);
} else {
mkdirs(path.dirname(dirname), function () {
fs.mkdir(dirname, callback);
});
}
});
}
//更新图片路径
function changeDir(par,index,userPath,callback) {
var keyArr = Object.keys(par.files);
if(keyArr.length < 1){
callback(null,par);
return;
}
var picObj = par.files[keyArr[index]][0];
var uploadedPath = picObj.path;
fs.readFile(uploadedPath, function (err,bytesRead) {
if (err) {
callback(err,par);
return;
}
var info = imageInfo(bytesRead);
var type;
if(!info || !info.format){
type = '.jpg';
}else {
type = imageInfoFileType(info.format);
if (!type) {
callback('上传图片格式有误', par);
return;
}
}
//参数正确 更换图片路径
var picPach = userPath + type;
var dstPath = mainPath + picPach;
checkDirs(dstPath,function (exits) {
if(exits){
picPach = userPath + (keyArr.length + index) + type;
dstPath = mainPath + picPach;
}
//重命名为真实文件名
fs.rename(uploadedPath,dstPath,function (err) {
if(err){
callback(err,par);
return;
}
par[picObj.fieldName] = picPach;
if(index < (keyArr.length-1)){
changeDir(par,index+1,userPath,callback);
}else {
callback(null,par);
}
});
});
});
}
if(par.mp4_url) {
if(!files.mp4_url || !files.mp4_url[0] || !files.mp4_url[0].size || files.mp4_url[0].size == 0) {
cb('视频上传时发生错误!', 400);
return;
}
if(files.mp4_url[0].size > 8000000) {
fs.unlink(par.mp4_url, function () {});
cb('文件文件过大',400);
return;
}
delete files['mp4_url'];
delPicsWithFiles(files);
pathDir = 'bbs_mp4';
checkParFunc(par, function (err,errCode) {
if(err){
fs.unlink(par.mp4_url, function () {});
return cb(err, errCode);
}
picHelp.renameVideo(par,pathDir,isNeedUid,function (err,errCode,param) {
if(err){
cb(err,errCode,param);
fs.unlink(par.mp4_url, function () {});
return;
}
cb(null, 0, param);
});
return;
});
}
//文件上传
picHelp.renameVideo = function (par,picType,isNeedUid,cb) {
var uid = 0;
if(par.userInfo){
uid = par.userInfo.main_userInfo ? par.userInfo.main_userInfo.uid : par.userInfo.uid;
}
var date = new Date();
var userPath = '/' + picType;
userPath += '/' + date.getFullYear();
userPath += '/' + (date.getMonth()+1);
userPath += '/' + date.getDate();
if(isNeedUid == true) {
userPath += '/' + parseInt(uid / 100);
userPath += '/' + uid;
}
mkdirs((mainPath + userPath),function (err) {//创建目录
if(err){
cb(err,400);
return;
}
userPath += '/' + date.getHours() + date.getMinutes() + date.getSeconds() + date.getMilliseconds();
var uploadedPath = par.mp4_url;
fs.readFile(uploadedPath, function (err) {
if (err) {
cb(err, 400);
return;
}
var type = par.mp4_url.split('.')[1];
var picPach = userPath + '.' + type;
par.mp4_name = picPach;
var dstPath = mainPath + picPach;
checkDirs(dstPath,function (exits) {
if(exits){
picPach = userPath + type;
dstPath = mainPath + picPach;
}
fs.rename(uploadedPath,dstPath,function (err) {
if(err){
cb(err,400);
return;
}
par.mp4_url = par.mp4_name;
cb(null, 0, par);
});
});
});
});
}
https://gitee.com/mqzuimeng_admin/wx_blog.git
本文分享自微信公众号 - 程序猿周先森(zhanyue_org)。
如有侵权,请联系 [email protected] 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。