概述
继上一篇条记介绍怎样绑定七牛云的域名之后,这篇条记主要介绍了怎样在Vue3项目中实现文件上传至七牛云的功能。我们将利用Cropper.js来处置惩罚图像裁剪,并通过自界说组件和API调用来完成整个流程。
这里直接给出关键部门js代码,上传之前要先获取一个上传凭据,这里是由后端接口生成的具体的实当代码在后文有体现,这里实现的功能逻辑为:将上传的图片转化为base64数据之后调用uploadToQiniu 方法。
uploadToQiniu 方法实现为:
- 将base64的数据解码出数据范例或直接利用默认范例
- 调用父组件的props.nickname设置文件名称这一步可以自界说实现
- 调用useFileApi().upload() 接口获取上传凭据以及空间域名用于拼接图片访问url
- 将base64数据转为二进制数据
- 动态导入qiniu-js (PS:这里用动态导入的原因是直接导入会导致父组件加载子组件的时候出现题目)
- 调用Qiniu.upload方法上传文件
- 跟踪上传进度这里用一个message弹框直接显示
- const uploadToQiniu = async (base64Image) => {
- // 提取Base64编码中的图片类型
- const base64Data = base64Image.split(',')[0];
- const typeMatch = base64Data.match(/data:(.+);base64,/);
- const type = typeMatch ? typeMatch[1] : 'jpg';
- const nickname = (props.nickname || '匿名用户').replace(/[\\/:*?"<>|]/g, '').trim().substring(0, 50);
- const fileName = `${nickname}-avatar-${Date.now()}.${ type }`;
- const result = await useFileApi().upload(fileName);
- if (!result || !result.data) {
- ElMessage.error('未能获取上传凭证');
- return;
- }
- const { token, domain } = result.data;
- // 将base64转换为二进制数据
- const base64 = base64Image.split(',')[1];
- const byteCharacters = atob(base64);
- const byteNumbers = new Array(byteCharacters.length);
- for (let i = 0; i < byteCharacters.length; i++) {
- byteNumbers[i] = byteCharacters.charCodeAt(i);
- }
- const byteArray = new Uint8Array(byteNumbers);
- const file = new File([byteArray], fileName, { type: type });
- // 动态导入qiniu-js
- const Qiniu = await import("qiniu-js");
- const config = {
- useCdnDomain: true,
- region: 'z2',
- domain: domain, //配置好的七牛云域名
- chunkSize: 100, //每个分片的大小,单位mb,默认值3
- forceDirect: true //直传还是断点续传方式,true为直传
- };
- const putExtra = {
- fname: '',
- params: {},
- mimeType: type,
- };
- let uploadMessage = null; // 用于跟踪进度消息
- return new Promise((resolve, reject) => {
- const observable = Qiniu.upload(file, fileName, token, putExtra, config);
- const observer = {
- next(res) {
- if (uploadMessage === null) { // 确保只显示一次进度消息
- uploadMessage = ElMessage({
- message: '上传中...',
- duration: 0,
- type: 'success',
- onClose: () => {
- uploadMessage = null;
- }
- });
- }
- // 更新消息内容以显示进度,这里假设res.total === 100表示100%
- if (res.total === 100) {
- uploadMessage.close();
- }
- },
- error(err) {
- if (uploadMessage) {
- uploadMessage.close(); // 关闭进度消息
- }
- ElMessage.error('上传失败: ' + err.message);
- reject(err);
- },
- complete(res) {
- if (res.key) {
- if (uploadMessage) {
- uploadMessage.close();
- }
- resolve(`http://${domain}/${res.key}`);
- } else {
- if (uploadMessage) {
- uploadMessage.close();
- }
- reject(new Error('上传成功,但未获取到文件key或域名'));
- }
- },
- };
- observable.subscribe(observer);
- });
- };
复制代码 下面是一个完备的前后端部门代码
技能栈
- 前端框架: Vue3
- 状态管理: Pinia
- UI库: Element Plus
- 图像裁剪工具: Cropper.js
- 后端语言: Python (FastAPI)
- 存储服务: 七牛云
实现步骤
1. 安装依赖
起首,确保你已经安装了必要的npm包:
- npm install cropperjs element-plus pinia qiniu-js
复制代码 2. 创建用户信息组件
创建一个名为Personal.vue的组件,用于展示和编辑用户信息。
前端代码比较多这里这展示关键部门js代码 源码在文末
[code]<!-- 设置头像组件 通过updateAvatar传递到父组件 通过nickname传递到子组件 -->
<SeePictures ref="SeePicturesRef"
@updateAvatar="updateAvatar"
:nickname="state.personalForm.nickname"
></SeePictures>
const SeePictures = defineAsyncComponent(() => import("/@/components/seePictures/index.vue"))
const SeePicturesRef = ref();
// 打开裁剪弹窗
const onCropperDialogOpen = () => {
nextTick(() => {
SeePicturesRef.value.openDialog(state.personalForm.avatar);
});
};
const save = async () => {
// 保存用户信息
await useUserApi().saveOrUpdate(state.personalForm)
await getUserInfo()
ElMessage.success("更新成功!╰(*°▽°*)╯ |