这是我参与11月更文挑战的第20天,活动详情查看:2021最后一次更文挑战
上传功能的实现
- 将上传表单的类型置为file.
注意:name属性不可缺少。
<li>菜品图片:<input type="file" name="picUrl" /></li>
复制代码
- 配置文件上传的模式
// 配置文件上传的模式
config.multipart = {
mode: 'file'
};
复制代码
- 配置csrf属性
enctype属性不可缺少。
<form action="/<%=adminPath%>/product/doAdd?_csrf=<%=csrf%>" method="post" enctype="multipart/form-data">
复制代码
- 将路由设置为post
router.post(`/${config.adminPath}/product/doAdd`,controller.admin.product.doAdd);
复制代码
- 控制器中读取file
async doAdd() {
const {ctx} = this;
const body = ctx.request.body;
const file = ctx.request.files[0];
ctx.body = {
body: body,
file: file
}
}
复制代码
将上传的文件保存在指定的位置
- 安装工具包
npm i mz mz-modules --save
复制代码
- 在控制器中引入相关工具包
const path = require('path');
const fs = require('mz/fs');
const pump = require('mz-modules/pump');
复制代码
- 创建上传到哪个文件夹,这个文件夹要提前创建好(public/upload)
- 控制器读写逻辑的实现
async doAdd() {
const {ctx} = this;
const body = ctx.request.body;
const file = ctx.request.files[0];
// 获取文件名称
const filename = file.filename;
const targetPath = path.join('app/public/upload',filename);
// 读取文件
const source = fs.createReadStream(file.filepath);
// 创建写入流
const target = fs.createWriteStream(targetPath);
try {
await pump(source,target);
} finally {
await ctx.cleanupRequestFiles();
}
ctx.body = "写入成功"
}
复制代码
实现多文件上传
- 静态页面设置如下所示:
- 控制器的核心实现逻辑
// 实现多文件上传
async doAdd() {
const { ctx } = this;
const body = ctx.request.body;
const files = ctx.request.files;
try {
for (let file of files) {
const filename = file.filename;
const targetPath = path.join('app/public/upload', filename);
// 读取文件
const source = fs.createReadStream(file.filepath);
// 创建写入流
const target = fs.createWriteStream(targetPath);
await pump(source,target);
}
} finally {
await ctx.cleanupRequestFiles();
}
ctx.body = {
body, files
}
}
复制代码
以日期文件夹进行分类上传图片
下面是实现的效果:
- 在service中引入相关工具包
const sd = require('silly-datetime');
const path = require('path');
const mkdirp = require('mz-modules/mkdirp');
复制代码
- 在配置文件中定义上传的路径
// 配置上传图片时的拼接路径
config.uploadDir = "app/public/upload";
复制代码
- 在service中定义创建路径和文件夹的函数
async getUploadFile(filename) {
// 获取当前的日期
let day = sd.format(new Date(),'YYYYMMDD');
// 创建图片的保存路径
let dir = path.join(this.config.uploadDir,day);
await mkdirp(dir);
// 生成文件名称
let unix = this.getUnixTime();
let saveDir = path.join(dir,unix + path.extname(filename));
return saveDir;
}
复制代码
- 在控制器中异步调用文件路径
const targetPath = await this.ctx.service.tools.getUploadFile(filename);
复制代码
下面附录下全部的控制器代码
async doAdd() {
const { ctx } = this;
const body = ctx.request.body;
const files = ctx.request.files;
try {
for (let file of files) {
const filename = file.filename;
// const targetPath = path.join('app/public/upload', filename);
const targetPath = await this.ctx.service.tools.getUploadFile(filename);
// 读取文件
const source = fs.createReadStream(file.filepath);
// 创建写入流
const target = fs.createWriteStream(targetPath);
await pump(source,target);
}
} finally {
await ctx.cleanupRequestFiles();
}
ctx.body = {
body, files
}
}
复制代码