研究了好一阵子,踩了无数的坑,查阅了很多的博客,ai也用了,最后做出来了,保准清晰明了的告诉你你需要什么就可以实现这个功能。
前端方面
1.首先是组件的使用
这里建议使用组件库里的代码,这一篇主要讲最关键的点,下一篇会讲el-upload怎么调整
最关键的就是这三个,可以说组件这里设置好了这三个,前端就可以了
2.内容方面
//上传用户头像涉及的变量 let FormDatas = reactive(""); //上传给后端的变量 // 上传之前,这里差不多照抄即可 const beforeUpload = (rawFile) => { //这里设置上传图片类型和限制大小 if (rawFile.type !== "image/jpeg" && rawFile.type !== "image/png") { ElMessage.error("头像必须是jpg或png格式!"); return false; } else if (rawFile.size / 1024 / 1024 > 5) { ElMessage.error("头像过大!"); return false; } return true; }; // 上传头像 const uploadFile = async (item) => { //上传头像的处理 FormDatas = new FormData(); FormDatas.append("file", item.file); };
这里讲一下上传头像,需要转换成FormData格式,这一点很关键,然后这个FormDatas就是我要传给后端的东西,就是上传的内个文件,这里是全局变量
还有注意一下这里的这个append的键“file”
3.发送请求和一些逻辑
//这里是我的表单点击提交之后的逻辑 //先请求 let uploadMsg = await proxy.$api.upload(FormDatas); //拿到数据之后给表单里的avatar赋值成链接,这部分之后是更新用户信息的请求 if (uploadMsg) { userForm.avatar = uploadMsg.data; } //上传头像的请求(可能不需要设置headers,但是我加上了) upload(params) { return request({ headers: { "Content-Type": "multipart/form-data" }, url: "/upload/img", method: "post", data: params, }); },
这部分是大家自己的逻辑代码,就是带着这个数据去请求然后能拿回来一个图片地址
后端方面
这里比较关键,因为我对后端不了解,所以基本查阅的资料都是关于后端koa框架的,真的踩了很多坑!
1.首先是app.js里面
const bodyparser = require("koa-bodyparser"); // middlewares app.use( bodyparser({ enableTypes: ["json", "form", "text"], }) );
这里其实用这个中间件就可以解析,不需要加任何额外的中间件,尤其是koa-body!!!
尤其是koa-body!!!一查博客全都告诉你加koa-body解析formdata数据,确实能解析了,但是存到了ctx.request.files里面!你的koa-multer就不生效了!真的很坑!
2.upload.js文件
//这里没什么好说的,照抄即可,是根据日期创建文件夹和文件名称 let storage = multer.diskStorage({ //设置文件存储位置 destination: function (req, file, cb) { let date = new Date(); let year = date.getFullYear(); let month = date.getMonth() + 1; let day = date.getDate(); let dir = "./public/uploads" + year + month + day; //如果没有文件夹就创建文件夹 if (!fs.existsSync(dir)) { fs.mkdirSync(dir, { recursive: true, }); } cb(null, dir); }, filename: function (req, file, cb) { //设置文件名称 let filename = Date.now() + path.extname(file.originalname); cb(null, filename); }, }); let upload = multer({ storage }); //上传图片的接口 router.post("/img", upload.single("file"), async (ctx) => { let path = ctx.req.file.path; path = ctx.origin + "" + path.replace("public", ""); if (path) { ctx.body = { code: 200, msg: "上传成功!", data: path, }; } else { ctx.body = { code: 400, msg: "上传出现异常!", }; } });
注意一下上传图片接口里的upload.single("file"),这里要和前端append的名字对上,然后你就可以从ctx.req里面拿到file,大家可以自行打印,然后这里是把图片存到了后端项目的一个文件里面,启动后端之后就可以通过后端服务器的地址访问这个图片,然后数据库存的是这个地址(后面有图)
还有req和request不是一个东西!
所以我可能是这个地方没对上(当时某一个用的myfile),绕了一大圈子(痛!太痛了!)
下一篇讲一下设置el-upload
附带的加强理解的点
1.前端根据后端返回的path放图的代码
// 头像,如果上传了就从store里面拿,没上传就是默认的 const picture = computed(() => { return userMsgStore.userMsg.avatar == "" ? "src/assets/imgs/defaultImg.png" : userMsgStore.userMsg.avatar; });