每个项目产品都会让你加埋点,你是愿意花几天一个个加,还是愿意几分钟一个小时加完去喝茶聊天?来试试这520web工具, 高效加埋点,目前我们公司100号前端都在用,因为很好用,所以很自然普及开来了,推荐给大家吧
自己开发所以免费,埋点越多越能节约时间,点两下埋点就加上了,还不会犯错,里面有使用视频,反正免费 😄
一、需求
本篇文章基于之前的文件续写, 因此一些基的使用需要参照下面的文章内容,不在重复基本代码
之前写了一篇文章,关于使用 koa-body
进行文件上传的,基本的代码不再重复,文章地址如下:
使用 koa-body
无法向 multer
直接通过 diskStorage
进行存储路径和文件名的配置,需要借助 onFileBegin:(name,file)=>{}
进行。
上传的基目录是 public/upload
,但是需要根据日期构建文件夹,并且文件名使用Date.now()+Math.random()
生成,其实文件名是可以直接使用默认的就挺好,自己生成主要是方便演示。
最终的结果是:
public/upload/20180621/123123123123.txt
onFileBegin
会传递两个参数,一个是 name
,这个 name
是表单的 name 属性传递过来的,而 file
是一个 File
类型的对象,主要的属性如下:
属性名 | 说明 |
---|---|
size | 文件大小 |
path | 文件上传的路径(注意不是最终的路径) |
name | 文件的原始名称 |
type | 文件类型 |
hash | 如果配置了 hash 之后会有值 |
lastModifiedDate | 最近修改时间 |
二、实现
为了更好的实现需求,封装了一些基本的工具方法。
1、生成文件夹名称
文件路径:
utils/getUploadDirname.js
function getUploadDirName(){
const date = new Date();
let month = Number.parseInt(date.getMonth()) + 1;
month = month.toString().length > 1 ? month : `0${month}`;
const dir = `${date.getFullYear()}${month}${date.getDate()}`;
return dir;
}
module.exports = getUploadDirName;
2、检查文件夹路径是否存在,如果不存在则创建文件夹
koa-body
的文件件上传目录必须保证文件夹的存在,否则无法写入,因此需要判断文件夹是否存在,如果不存在,则新建一个文件夹即可。
文件路径:
utils/checkDirExist.js
/**
* @description 判断文件夹是否存在 如果不存在则创建文件夹
*/
const path = require('path');
const fs = require('fs');
function checkDirExist(p) {
if (!fs.existsSync(p)) {
fs.mkdirSync(p);
}
}
module.exports = checkDirExist;
3、获取文件的后缀
如果使用默认文件上传后的名字,则不需要这个方法,因为 koa-body
配置 formidable:{keepExtensions: true,}
之后会直接保留原始的文件后缀。
获取文件后缀依靠的是 file.name
属性,通过原始文件名获取到后缀。
文件路径:
utils/getUploadFileExt.js
function getUploadFileExt(name) {
let ext = name.split('.');
return ext[ext.length - 1];
}
module.exports = getUploadFileExt;
4、在 onFileBegin
中进行属性重赋值
有了助手方法之后,直接引入并且在 koa-body
的方法中使用即可。
文件路径:
app.js
以下代码中 koaBody()
/ getUploadDirName()
/ checkDirExist()
/ getUploadFileName()
均已经引入。
app.use(koaBody({
multipart:true,
encoding:'gzip',
formidable:{
uploadDir:path.join(__dirname,'public/upload'),
keepExtensions: true,
maxFieldsSize:2 * 1024 * 1024,
onFileBegin:(name,file) => {
// console.log(file);
// 获取文件后缀
const ext =getUploadFileExt(file.name);
// 最终要保存到的文件夹目录
const dir = path.join(__dirname,`public/upload/${getUploadDirName()}`);
// 检查文件夹是否存在如果不存在则新建文件夹
checkDirExist(dir);
// 重新覆盖 file.path 属性
file.path = `${dir}/${getUploadFileName(ext)}`;
},
onError:(err)=>{
console.log(err);
}
}
}));
三、效果
除了上面的一些变动外,其他的代码均不需要变动,最终上传的文件如下:
文件上传后的信息如下:
{
"photo": {
"size": 907,
"path": "E:\\Aprojects\\node_projects\\koa2\\20180619\\demo1\\public\\upload\\20180621/15295654622244128.txt",
"name": "新建文本文档.txt",
"type": "text/plain",
"mtime": "2018-06-21T07:17:42.226Z"
}
}
四、只保存需要的文件路径
虽然文件上传之后会有 path
属性,但是实际上这个 path
属性对我们的帮助不是很大,最终我们需要 20180621/15295654622244128.txt
这个路径而已。
因此需要修改一下 onFileBegin
的部分代码(其中一些代码变动了,和上面并不一样,但只是方便最后两行代码而已,功能没有变化):
onFileBegin: (name, file) => {
// console.log(file);
// 获取文件后缀
const ext = getUploadFileExt(file.name);
// 最终要保存到的文件夹目录
const dirName = getUploadDirName();
const dir = path.join(__dirname, `public/upload/${dirName}`);
// 检查文件夹是否存在如果不存在则新建文件夹
checkDirExist(dir);
// 获取文件名称
const fileName = getUploadFileName(ext);
// 重新覆盖 file.path 属性
file.path = `${dir}/${fileName}`;
app.context.uploadpath = app.context.uploadpath ? app.context.uploadpath : {};
app.context.uploadpath[name] = `${dirName}/${fileName}`;
},
关键代码是下面两行:
因为是支持多文件上传的,因此 app.context.uploadpath
应该能够存放多个文件才可以,所以和 ctx.request.files
采用了一样的存储规则,通过 name
属性作为 key 。
其中需要判断一下 app.context.uploadpath
是否存在, 如果不存在则置空对象,否则会报错误,无法设置属性。
app.context.uploadpath = app.context.uploadpath ? app.context.uploadpath : {};
app.context.uploadpath[name] = `${dirName}/${fileName}`;
经过这两行之后,就可以在路由中的上下文中获取到上传后的文件信息:
router.post('/',async (ctx)=>{
// console.log(ctx.request.files);
console.log(ctx.uploadpath);
ctx.body = JSON.stringify(ctx.request.files);
});
结果:
{ photo: '20180621/15295684564254069.txt' }
五、示例代码
在 github 上存了一份示例代码,可以通过修改index.html
控制单个文件上传或者多个文件上传
结果:
{
"photo[]":[{"size":1200,"path":"E:\\Aprojects\\node_projects\\koa2\\20180619\\demo1\\public\\upload\\2018073/15306331757424476.png","name":"arrow.png","type":"image/png","mtime":"2018-07-03T15:52:55.743Z"},{"size":11536,"path":"E:\\Aprojects\\node_projects\\koa2\\20180619\\demo1\\public\\upload\\2018073/15306331757425633.jpg","name":"2.jpg","type":"image/jpeg","mtime":"2018-07-03T15:52:55.744Z"},{"size":15633,"path":"E:\\Aprojects\\node_projects\\koa2\\20180619\\demo1\\public\\upload\\2018073/15306331757442120.jpg","name":"1.jpg","type":"image/jpeg","mtime":"2018-07-03T15:52:55.748Z"}],
"photo2":{"size":1200,"path":"E:\\Aprojects\\node_projects\\koa2\\20180619\\demo1\\public\\upload\\2018073/15306331757486132.png","name":"arrow.png","type":"image/png","mtime":"2018-07-03T15:52:55.749Z"}
}