当前位置: 首页 > Web前端 > vue.js

Koa&Mongoose&Vue实现前后端分离--11更新用户头像

时间:2023-03-31 17:26:38 vue.js

上节回顾更新用户文本数据工作内容更新用户数据图片上传&存储&静态访问准备npmi-Skoa-static//首先切换到/server目录下的业务逻辑服务器文件routing配置服务器拦截路由请求://新建文件:server/router/assets.jsconstRouter=require('@koa/router');constcontrols=require('../control/assets');constrouterUtils=require('../utils/router');const{upload}=控件;constrouter=newRouter({prefix:'/assets'});constroutes=[{path:'/:category/:id',method:'POST',handle:upload}]routerUtils.register.call(router,routes);module.exports=router;//创建一个新文件:server/control/assets.jsasyncfunctionupload(ctx,next){console.log('--------upload========')}module.exports={upload,}koa-body支持//更新文件:server/app.js...constpath=require('path');...app.use(bodyParser({multipart:true,//支持文件数据formidable:{uploadDir:path.resolve(__dirname,'./public/temp'),//图片存放位置keepExtensions:true}}));...multipart:true支持文件数据。这里以key:value的形式获取formidable.uploadDir文件上传存储位置。如果不设置,则默认存放在电脑用户目录的缓存位置。最好设置一个可控的位置。keepExtensions:true是否保留后缀名,默认不保留。Postman测试前期,登录时,全局变量tokenBody-->form-data-->File-->SelectFiles请求结果:无返回。vscode调试控制台反馈:设置存储文件路径不存在。保存文件存放路径不存在。需要检查文件目录是否存在。如果不存在,请创建一个新的。//新文件:server/utils/dir.jsconstpath=require('path');constfs=require('fs');functioncheckDirExist(dirname){if(fs.existsSync(dirname)){返回真;}else{if(checkDirExist(path.dirname(dirname))){fs.mkdirSync(dirname);//递归返回真;}}}module.exports={checkDirExist,}方法一,通过koa-body配置//更新文件:...const{checkDirExist}=require('./utils/dir');constfileTempDir=path.resolve(__dirname,'./public/temp');...app.use(bodyParser({multipart:true,formidable:{uploadDir:fileTempDir,keepExtensions:true,onFileBegin(key,file){//使用钩子函数checkDirExist(fileTempDir);//file.path=path.resolve(fileTempDir,file.name)//文件重命名}}}));利用koa-body配置onFileBegin,可以在处理文件之前进行一些操作,如:测试目录是否存在,重命名,改变存储path等测试结果:方法二,fs模块读写文件,为什么要用第二种方法?使用koa-body配置onFileBegin重命名只能获取文件数据本身的数据信息,无法获取ctx的上下文信息(比如这里我们要根据请求参数创建一个目录存储文件)。//更新文件:server/control/assets.jsconstfs=require('fs');constpath=require('路径');const{checkDirExist}=require('../utils/dir');异步函数上传(ctx,next){constfile=Object.values(ctx.request.files)[0];const{类别,id}=ctx.params;constfilePath=file.path;//要保存到文件夹路径的最终文件constdir=path.join(__dirname,`../public/${category}/${id}/`);try{//检查文件夹是否存在-->如果不存在,则创建一个新文件夹checkDirExist(dir);constreader=fs.createReadStream(filePath);constwriter=fs.createWriteStream(path.resolve(dir,file.name));读者.管道(作者);//删除缓存文件fs.unlinkSync(filePath)}catch(err){}}module.exports={upload}这里根据上传路由的参数,将文件存放在用户ID创建的头像目录下.Postman测试结果:访问文件此时访问文件:因此需要将public目录加入unless白名单进行身份认证://Updatefiles:server/app.js...custom:function(ctx){const{方法,路径,查询}=ctx;如果(路径==='/'){返回真;}if(/^\\/public/.test(path)){//公共目录returntrue;}if(path==='/users'&&query.action){returntrue;}returnfalse;}...继续访问:这是因为默认请求的是动态资源,而图片数据是静态资源//更新文件:...constkoaStatic=require('koa-static');...//中间件:指定静态资源路径vs.与动态资源分离app.use(koaStatic(path.join(__dirname,'public/')))继续访问,报错如上:这是因为访问路径错误:不要在访问路径中包含/public。如果怀疑,就不要加koa-static,如果只修改路径就可以访问的话可以自己试试。服务端更新用户头像逻辑上述内容修改了上传的业务逻辑,只涉及将文件保存到指定路径,不更新用户头像信息,服务端不返回数据。//更新文件:server/control/assets.jsconstfs=require('fs');constpath=require('路径');constuserModel=require('../model/user');const{checkDirExist}=require('../utils/dir');异步函数上传(ctx,next){constfile=Object.values(ctx.request.files)[0];const{category,id}=ctx.params;//用户头像远程地址constremotePath=`${ctx.origin}/${category}/${id}/${file.name}`;constfilePath=file.path;constdir=path.join(__dirname,`../public/${category}/${id}/`);尝试{checkDirExist(dir);constreader=fs.createReadStream(filePath);constwriter=fs.createWriteStream(path.resolve(dir,file.name));读者.管道(作者);try{//更新用户头像信息awaituserModel.updateOne({_id:id},{avatar:remotePath}).exec();}catch(err){ctx.body={code:'404',data:null,msg:'Uploadfailed'};返回;}fs.unlinkSync(filePath)ctx.body={code:'200',data:{filePath:remotePath},msg:'上传成功'}}catch(err){ctx.body={code:'404',data:null,msg:'Uploadfailed'}}}module.exports={upload}设置远程访问地址${ctx.origin}/${category}/${id}/${file.name}并更新地址为用户信息这里删除/server/public目录,重新测试:前端页面头像逻辑//updatefile:...methods:{...handleAvatarSuccess(res,file){this.imageUrl=URL.createObjectURL(file.raw)},beforeAvatarUpload(file){constisJPG=/^image\//.test(file.type)constisLt2M=file.size/1024/1024/10<2if(!isJPG){this.$message.error('上传的头像只能是JPG格式!')}if(!isLt2M){this.$message.error('上传的头像不能超过20MB!')}returnisJPG&&isLt2M},...data(){return{uploadForm:{action:`//localhost:3000/assets/avatars/${this.$store.state.loginer.id}`,headers:{'Authorization':`Bearer${localStorage.getItem('token')}`},multiple:false,'show-file-list':false,'on-success':this.handleAvatarSuccess,'before-upload':this.beforeAvatarUpload},...异步created(){constres=awaithttp.get(`/users/${this.userId}`)if(res.code==='200'){this.loginer=res.datathis.dialogForm.form={...res.data}this.imageUrl=res.data.avatar//初始化,赋值}else{this.$message({type:'error',message:'获取用户信息失败'})}}初始化时给头像赋值;通过uploadForm设置上传配置on-success覆盖原值;before-upload上传前,verify检查文件类型和大小;效果展示:参考文档koa-statickoa-body上传文件相关配置