前端:
思路:
html:设置头像的img,设置input的type为file,hidden隐藏input,通过点击img事件触发input事件
js:点击input事件后拿到文件,创建formdata对象,在formdata添加数据发送给后端
html部分:
<input
type="file"
hidden
name="avatar"
ref="upfile"
accept="image/png, image/jpeg, image/jpg"
@change="upImg"
/>
<img :src="userInfo.avatar_url" alt @click="handleUploadAvator" />
js部分:
1.js触发input事件:
// 获取input 实例
const upfile = ref(null)
//点击头像后触发input事件
const handleUploadAvator = () => {
upfile.value.click()
}
2.这样点击图像后,upImg的change就触发了,接下来把文件数据发送给后端:
const upImg = (e) => {
const file = e.target.files[0] // 拿到上传的file,这个file里有name,size,type等
const param = new FormData() // 创建form对象
param.set('avatar', file) // 为创建的form对象增加上传的文件
// 这里是封装的axios,具体封装在下一个代码块
upAvator(param)
.then((res) => {
// 在这里可以触发vuex的mutations更新存在vuex的头像
// 关于刷新后vuex丢失,读取不出数据可以用插件vuex-persistedstate存在localstorage就可实现刷新页面更新头像了
console.log(res, 'res')
})
.catch((err) => {
console.log(err, '出现了错误')
})
}
3.upAvator请求:
export const upAvator = (file) => {
return request({
url: '/upload/avatar',
method: 'POST',
//这里想请求拦截里,后面总失效后面研究一下再回来改
headers: {
'Content-Type': 'multipart/form-data',
Authorization: `Bearer ${store.getters.token}`
},
data: file
})
}
以上完成,前端就实现了formdata发送。
后端(node koa):
router:
fileRouter.post("/avatar", verifyAuth, avatarHandler, saveAvatarInfo);
verifyAuth验证token:
const verifyAuth = async (ctx, next) => {
// 1.获取token
const authorization = ctx.headers.authorization;
if (!authorization) {
const error = new Error(errorType.UNAUTHORIZATION);
return ctx.app.emit("error", error, ctx);
}
const token = authorization.replace("Bearer ", "");
// 2.验证token(id/name/iat/exp)
try {
const result = jwt.verify(token, PRIVATE_KEY, {
algorithms: ["RS256"],
});
ctx.user = result;
await next();
} catch (err) {
const error = new Error(errorType.UNAUTHORIZATION);
ctx.app.emit("error", error, ctx);
}
};
avatarHandler 用multer处理图片:
const path = require("path");
const Multer = require("koa-multer");
const { AVATAR_PATH} = require("../constants/file-path");
const avatarUpload = Multer({
dest: AVATAR_PATH,
});
const avatarHandler = avatarUpload.single("avatar");
controller:
async saveAvatarInfo(ctx, next) {
//1.获取头像相关信息
const { filename, mimetype, size } = ctx.req.file;
const { id } = ctx.user;
//2.图像信息储存数据库
const result = await fileservice.createAvatar(
filename,
mimetype,
size,
id,
permission_id
);
//3.图像地址储存users表中
const avatarUrl = `${APP_HOST}:${APP_PORT}/users/${id}/avatar`;
await userService.updateAvatarUrlById(avatarUrl, id);
ctx.body = {
message: "头像创建成功",
avatarUrl: avatarUrl,
};
// console.log(ctx.req.file);
}
service:
//根据用户id更新头像url
async updateAvatarUrlById(avatar, userId) {
const statement = ` UPDATE users SET avata = ? WHERE id = ?;`;
const result = await connection.execute(statement, [avatar, userId]);
return result;
}