vue3+koa实现文件上传功能的全过程记录
大四小菜鸡 人气:0前言:
在完成自己的毕设中,需要引入文件上传,前后找到资料实现了图片上传,在此做一个总结
技术引用:
1. 使用了 koa-body 实现后台文件上传功能
2. 使用了 koa-static 实现后台资源静态访问
3. 使用了 Element plus UI的upload组件实现前端文件上传
前端实现
代码实现:
<el-upload v-model:file-list="fileList" class="upload-demo" action="/api/article/upload" :limit="1" :on-remove="handleRemove" :on-change="handlePreview" :on-success="handleSuccess" list-type="picture" :headers="{ Authorization: headers }" accept="image/jpeg,image/png" > <el-button type="primary">Click to upload</el-button> <template #tip> <div class="el-upload__tip"> jpg/png files with a size less than 500kb </div> </template> </el-upload>
其中介绍几个重要的需要用到的属性:
action="/api/article/upload" // 向该目录下发送接口 :on-remove="handleRemove" //删除图片触发的回调事件 :on-change="handlePreview" //触发图片新增之类的修改触发的回调事件 :on-success="handleSuccess" //向action路径下发送接口请求的响应的回调函数 :headers="{ Authorization: headers }" // 向请求头携带字段,因为我这里使用了Token,需要在请求前携带Authorization accept="image/jpeg,image/png"//接受的文件类型方便挑选。
handleSuccess 方法的第一哥参数response就是访问/api/article/upload后的响应结果,这个结果就是我们将图片放在静态资源目录的基本地址basePath,我这边 封装了一下, imgPath的结果如下: { imgBathPath:upload_4f60af0c9732ab4a1463e29c4bbc8c04.jpg, imgName:"xxxx"},拥有图片的地址和图片名字,用于查看时候的回显。
const handleSuccess = (response) => { console.log(response.data, "--------"); imgPath.value = response.data; };
后台实现:
引入koa-body,并注册中间件:
app.use(koabody({ multipart: true, //开启文件上传 formidable: { // 路径配置 // 在配置选项option 不推荐使用相对路径 uploadDir: path.join(__dirname, './upload'), //配置保存路径 keepExtensions: true //保存文件扩展名 } }))
在配置完koa-body 后,就可以通过 const { file } = ctx.request.files; 拿到本次文件上传的图片的一些信息。再进行后端检验,只接受图片类型文件的上传,不然返回失败:
router.post('/upload', async (ctx) => { // console.log(ctx.request.files, "ctx.request.files") const { file } = ctx.request.files; const fileTypes = ["image/jpeg", "image/png"] if (file) { if (fileTypes.includes(file.type)) { ctx.body = util.success({ imgName: file.name, imgBathPath: path.basename(file.path) }, "上传成功") } else { ctx.body = util.fail("上传图片非jpg 和 png 格式") } } else { ctx.body = util.fail('上传出错') } // ctx.body = util.success(ctx.request.files.file.path, "上传成功") })
引入koa-static 进行静态资源访问
app.use(koaStatic(path.join(__dirname, './upload')))//开启静态资源访问
之后,./upload文件下就是静态资源了,我们可以直接访问,如:
前台回显图片:
首先我们接口返回的数据结果如下:
const mongoose = require('mongoose') const articleSchema = mongoose.Schema({ articleTitle: String, // 文章标题 articleType: String, // 文章类型 articleContent: String, // 内容,富文本 publishState: Number, // 发布状态 0 未发布 1 已发布 2已删除 articleAuth: String, imgPath: { imgName: String, imgBathPath: String, }, applyUser: { userId: String, userName: String, userEmail: String }, publishTime: { type: Date, }, createTime: { type: Date, default: Date.now } // 创建事件 }) module.exports = mongoose.model("article", articleSchema, "article")
我们在渲染列表的时候,就已经得到了所有信息,现在只需要点击查看回显信息而已
const handleView = (row) => { action.value = "view"; // 设置action状态,用来判断disable条件 let data = { ...row }; //遍历弹窗数据 // 将文本编辑器设置为只读 // const editor = editorRef.value; // editor.disable(); // 填充富文本到富文本编辑器中 articleContent.value = data.articleContent; // 处理图片的回显 const temp = { name: data.imgPath.imgName, url: "http://localhost:3000/" + data.imgPath.imgBathPath, }; fileList.value.push(temp); console.log(fileList.value, "fileList.value"); articleForm.value = data; showModal.value = true; };
效果如下:
遇到的问题:
已解决:
Token验证问题:
因为我全局加入了接口校验,导致在最初的时候我upload 的结果一致倒是400,未加入Token,并且在访问的时候也是一致报Token问题,这是俩个问题。在上传时候,是需要Token,也就是通过:header属性添加Authorazation。但是访问的时候报错,是因为我们访问静态资源的时候也是接口访问,需要在后台加上这段代码:对一些不需要的token进行的接口拦截放过,例如/api下的login接口,和非api开头的所有接口,也就是我们访问静态资源的接口。
app.use(koajwt({ secret: 'secret' }).unless({ // 过略一些不需要token的接口 // 过略掉除了 登录接口 和 非api接口(主要为静态资源请求接口) path: [/^\/api\/users\/login/, /^((?!\/api).)*$/], })) // 使用中间件进行token拦截
proxy代理问题:
在vue3 cli 的配置下,配置了proxy代理:这样访问以/api的接口都会跳转到/localhost:3000/api下。
proxy: { //拦截以api开始的请求,将/api 替换成http://localhost:3000, 浏览器同源策略,无法在前端 port:8080 访问后端 prot:3000 端口,需要借助代理拦截请求,进行接口转发 "/api": { target: "http://localhost:3000" } }
但现在我有一个问题,我们之前说到文件静态资源通过http://localhost:3000/upload_f16d68210c6822f1000ce11f363f0815.jpg 来访问,这个路径按上述思路配置代理:会导致前端路由也一起访问后端接口,导致一锅粥,这样是不对的。
"/": { target: "http://localhost:3000" },
最后只能采取死办法,引入koa-cors 实现后台跨域,并且通过绝对路径: url: "http://localhost:3000/"+ data.imgPath.imgBathPath,来访问。
总结:
本次完成毕设遇到的问题都是通过查看文档 + 百度查询的方式,当然这些方法在脑海里也有大致的印象,这次做一个总结。
加载全部内容