目录路径:
在实际项目中,一般都会有上传图片的需求,而在我们的项目文件中,使用thinkjs命令创建项目时,则会自动创建 www/static
目录,该目录下专门用来存放 JS、CSS、图片等静态资源。而在实现上传的图片保存在自己的项目中时,我们并不是一开始就在www底下创建一个固定的目录来存放已经上传的图片,而是通过thinkjs自动来根据需求来创建目录路径。
比如,在我们的项目中,存放简历的文件夹暂时先就叫做“jobFiles”,类似于:这个,jobFiles文件夹就是只有当图片上传的时候才会自动在存放在静态文件www/static目录下创建,而对于工作来说,这样子创建的文件夹就比较灵活,因为如果没有请求文件上传的方法时,也就不会产生这个文件夹,更加方便。而对于自动创建文件夹的方法,thinkjs官网也给了自己的方法:
think.mkdir(p, mode)
p {String} 要创建的目录 mode {Number} 要创建的目录权限,默认为 0777 递归的创建目录,如果目录已经存在,那么修改目录的权限。 // 假设 /home/welefen/a/b/ 不存在 think.mkdir("/home/welefen/a/b"); think.mkdir("home/welefne/a/b/c/d/e"); // 递归创建子目录
而要实现上图中在www/static/jobFiles/自动取时间/该文件这样的效果的话,就必须自己来写工具类方法:
①
/** * 获取未压缩图片路径___本地文件路径 * @param jpg 图片类型 * @returns {string} */ imgUtil.getLocalImageUrl = function (jpg) { let newDate = new Date(); let obj={timePath:timeutil.dateFormat(newDate.getTime() / 1000, '/yyyy/MM/dd/') ,fileName: newDate.getTime() + '.' + jpg}; return obj; };
②
/** * @fmt 格式化字符串 * @Date 为需要格式化的日期 * 示例:format(new Date(),'yyyy-MM-dd hh:mm:ss'); * 返回值为字符串 */ tUtil.dateFormat = function(pdate, fmt) { let date = new Date(Number(pdate) * 1000); if (date == "Invalid Date") { date = new Date(pdate); } if (null == date || undefined == date) return ''; var o = { "M+": date.getMonth() + 1, //月份 "d+": date.getDate(), //日 "h+": date.getHours(), //小时 "m+": date.getMinutes(), //分 "s+": date.getSeconds(), //秒 "S": date.getMilliseconds() //毫秒 }; if (/(y+)/.test(fmt)) fmt = fmt.replace(RegExp.$1, (date.getFullYear() + "").substr(4 - RegExp.$1.length)); for (var k in o) if (new RegExp("(" + k + ")").test(fmt)) fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length))); return fmt; };
③上传文件、图片的方法
/** * 上传图片 * @returns {*} */ async uploadAction() { let file = think.extend({}, this.file('file')); let originalFilename = file.originalFilename; let fPath = file.path; let suffix = fPath.substr(fPath.lastIndexOf(".") + 1);//取后缀 if (suffix == "jpg" || suffix == "png" || suffix == "jpeg" || suffix == "doc" || suffix == "docx" || suffix == "pdf") { let size = file.size / 1024;//文件大小转化为kb if (size < 300) { let fileObj = imgutil.getLocalImageUrl(suffix); var uploadPath = "static/jobFiles" + fileObj.timePath + fileObj.fileName; think.mkdir("static/jobFiles" + fileObj.timePath);// 递归创建子目录 if (think.isFile(fPath)) {//检测是否是文件,如果在不存在则返回 false fs.renameSync(fPath, uploadPath);//fs.renameSync(oldPath, newPath) return this.success({showName: originalFilename, path: '/jobFiles' + fileObj.timePath + fileObj.fileName }); } else { return this.fail("上传文件失败,请重新上传!"); } } else { return this.fail("文件过大,请上传小于300kb的文件!"); } } else { return this.fail("仅支持上传jpg,png,jpeg,doc,pdf格式文件!"); } }
在这里,特别注意的一个问题,也就是让自己找了很久的bug,就是上面写的upload方法中的定义的
var uploadPath = "static/jobFiles" + fileObj.timePath + fileObj.fileName;
之前就是因为自己写成了/static/jobFiles,这样在上传的方法中,连自己也不知道上传的文件被放在哪个文件夹里,最后在大神同事的指点下,才恍然大悟:thinkjs在递归创建目录时,如果自己将路径写成"/static/jobFiles..."的话,它就会去这个js文件中往上找/static/jobFiles,但是在这个js文件夹之上又找不到所谓的jobFiles文件夹,因此最终也就不知道上传的文件跑哪里了,但是如果将路径写成相对路径"static/jobFiles..."的话,它就会直接去静态文件"www"底下去找"static/jobFiles...",若没有此文件夹的话,就会按我们所想的去创建一个目录。
还有一点:上面的方法中,还有一句: fs.renameSync(fPath, uploadPath);//fs.renameSync(oldPath, newPath)
这个也是值得一提的知识点:(nodejs中的fs.renameSync)
方法说明:同步版的rename;
语法:
fs.renameSync(oldPath, newPath)
但是:由于该方法属于fs模块,使用前需要引入fs模块(var fs= require(“fs”) )
接收参数:(两个)oldPath——原路径 newPath——新路径
var fs = require('fs'); fs.renameSync('125.txt','126.txt');
也就是在实现上传功能后,必须使用fs.renameSync(oldPath,newPath)的方法把原文件名改成“时间戳.后缀”的形式,这样子才算完成整个文件长传功能。