项目背景
vue3发布已经有很长一段时间了Typescript文件上传,目前vue3的生态也趋于稳定; 自vue3发布以来,市面上很多UI组件库也进行了相应的更新,进一步与vue3同步,从而更好的兼容vue3的生态。 明天要讲的当然是我们做开发时经常遇到的一个功能模块,那就是文件的批量上传。 相信我第一次接触文件批处理这个功能模块时会遇到的一个问题是,当我获取到所有的文件流后,当我进一步封装获取到的文件流并上传到前端服务时,由于文件流的通过很大程度上造成上传成功的困难。 这个时候我们就会考虑使用阿里的oss这样的云服务来上传文件,让oss在中间做一层分发。 oss帮我们处理文件流程后Typescript文件上传,会成功返回给我们文件的相关信息和地址。 接下来我将演示一下功能模块的实现。 功能比较简单。 如果路人技术高手看到的话,希望能够给我一点启发! ! !
相关技术栈
vue3:vue3官方网站
element-puls:Vue3UI 框架|ElementPlus
axios:axios英文网站| axios API 英文文档 | 轴
阿里云服务OSS:安装-对象存储OSS-阿里云
打字稿:
相关业务功能的实现流程
HTML代码实现:
使用element-puls组件库的el-form组件、el-upload组件、el-dialog组件实现客户界面的解释
选择文件
相关element-puls组件API属性可以查看文档:
业务逻辑实现:
(1). 使用vue3组合API绑定并定义数据结构,TypeScript定义数据socket;
(2)。 点击取消时不显示弹窗,点击上传文件按钮时,实现了对获取的相关文件流的数据结构的封装并保存文件流;
(3)。 将文件流上传到阿里的oss服务,按照阿里oss文档封装oss上传方法,自定义文件名路径,并在上传oss时封装文件名路径;
(4)。 成功上传到oss后,保存返回的文件信息; 将保存的文件数据流通过对应的业务socket上传到前端服务,然后在前端服务中进一步处理后返回结构体给客户端
import { defineComponent, ref, toRefs, reactive, unref } from 'vue';
import type { ElMessage, UploadInstance, UploadProps, UploadRawFile } from "element-plus";
import { client, options } from '/@/utils/OSS';
import { random } from '/@/utils/randomUser';
interface File {
file: object;
list: object;
};
interface State {
isShowDialog: Boolean;
uploadFile: File;
};
export default defineComponent({
setup(props,{emit}) {
const upload = ref();
const formRef = ref(null);
const state = reactive({
isShowDialog: false,
uploadFile: {
file: [],
list: []
}
});
// 关闭弹窗
const closeDialog = () => {
state.isShowDialog = false;
};
// 取消
const onCancel = () => {
closeDialog();
};
// 上传文件时触发
const handleChange: UploadProps['onChange'] = (file,files) => {
state.uploadFile.file.push(file.raw);
};
// 将文件流上传oss
const onSubmit = () => {
const formWrap = unref(formRef) as any;
if (!formWrap) return;
formWrap.validate((valid: boolean) => {
if (valid) {
let data = new Date();
let Y = data.getFullYear();
let M = (data.getMonth() + 1);
let D = data.getDate();
let tiem = Y + '-' + M + '-' + D;
let list:any = [];
// 文件批量上传
state.fileForm.file.forEach((item:any,index:any) => {
// 自定义文件名路径
let fileName = '/crm/' + tiem + '/' + random('' ,10) + '.' + item.name.split('.')[1];
// 请求oss接口上传
client.put(fileName, item, {...options}).then((response:any) => {
// console.log(response);
if (response.res.statusCode == 200) {
list.push({
fileName: item.name,
fileSize: item.size,
fileType: item.type,
fileUrl: response.url
})
getList(list); // 获取oss返回数据
upload.value!.clearFiles(); // 上传成功后清空上传信息数据
};
}).catch((error:any) => {
console.log(error); // 错误返回
});
});
}
})
}
// 获取oss返回数据并将数据保存至后端服务进行处理保存
async function getList(data:any) {
state.uploadFile.list = data;
if (data.length == state.uploadFile.file.length) {
...业务接口请求,将文件流数据返回给后端服务那边
}
};
return {
upload,
formRef,
state,
closeDialog,
onCancel,
handleChange,
onSubmit
};
}
});
将文件流上传到阿里的oss服务,根据阿里oss文档封装oss上传方法
// 封装oss方法
import OSS from 'ali-oss';
// 实例化OSS,并配置OSS信息
export const client = new OSS({
region: "填写Bucket所在的区域,例如:oss-cn-guangzhou",
accessKeyId: "填写通过阿里云控制台创建的AccessKeyID",
accessKeySecret: "填写通过阿里云控制台创建的AccessKeySecret",
endpoint: "填写OSS访问域名",
bucket: "通过控制台或PutBucket创建的Bucket"
});
// 分片配置项
export const options = {
// 获取分片上传进度、断点和返回值。
progress: (p:any, cpt:any, res:any) => {
},
// 设置并发上传的分片数量。
parallel: 4,
// 设置分片大小。默认值为1 MB,最小值为100 KB。
partSize: 1024 * 1024,
// 设置请求头
headers: {
// 指定该Object被下载时的内容编码格式。
"Content-Encoding": "utf-8",
// 指定过期时间,单位为毫秒。
Expires: "1000",
// 指定Object的存储类型。
"x-oss-storage-class": "Standard",
// 指定Object标签,可同时设置多个标签。
"x-oss-tagging": "Tag1=1&Tag2=2",
// 指定初始化分片上传时是否覆盖同名Object。此处设置为true,表示禁止覆盖同名Object。
"x-oss-forbid-overwrite": "false",
},
// 指定上传文件类型
mime: "text/plain",
};