如何基于 vue3+el-upload 二次封装上传文件组件到阿里云 oss 附进度条
- 一、创建生成全局唯一标识符 方法
- 二、导入计算文件Md5(spark-md5)
- 三、安装依赖ali-oss
- 四、创建导出ali-oss 方法
- 五、创建上传文件 组件(完整代码)
- 六、引入使用组件
一、创建生成全局唯一标识符 方法
export function newGuid() {
function S4() {
return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1)
}
return S4() + S4() + S4() + S4() + S4() + S4() + S4() + S4()
}
二、导入计算文件Md5(spark-md5)
npm i spark-md5
三、安装依赖ali-oss
npm i ali-oss
四、创建导出ali-oss 方法
在utils文件夹下 创建alioss.ts,并接收所需要的阿里云oss地区、id、密钥、远程仓库名称
import OSS from 'ali-oss'
export function client<T>(accessKeyId: T, accessKeySecret: T) {
console.log('接收到的', accessKeyId, accessKeySecret)
var clients = new OSS({
region: 'oss-cn-beijing',
accessKeyId,
secure: true,
accessKeySecret,
bucket: 'cangku',
})
return clients
}
五、创建上传文件 组件(完整代码)
创建封装上传文件组件 (代码中需填写阿里云oss的id和密钥)
<template>
<div>
<el-progress
v-if="showPercentage"
style="margin-bottom: 15px"
:text-inside="true"
:stroke-width="20"
:percentage="percentage"
striped
striped-flow
/>
<el-upload
class="upload-demo"
:drag="drag"
:limit="limit"
:disabled="disabled"
:auto-upload="autoUpload"
:accept="accept"
:show-file-list="showFileList"
:action="action"
:multiple="multiple"
:http-request="httpRequest"
:before-upload="beforeUpload"
:on-progress="uploadFileProcess"
:on-success="handleAvatarSuccess"
:on-remove="handleRemove"
:on-exceed="handleExceed"
:on-change="handleChange"
>
<div v-if="drag">
<el-icon class="el-icon--upload"><upload-filled />el-icon>
<div class="el-upload__text">将文件拖到此处,或<em>点击上传em>div>
div>
<div v-else>
<el-button type="primary">点我上传el-button>
div>
el-upload>
div>
template>
<script setup lang="ts">
import { ref } from 'vue'
import { UploadFilled } from '@element-plus/icons-vue'
import SparkMD5 from 'spark-md5'
import { newGuid } from '@/utils/guid'
import { client } from '@/utils/alioss'
import { ElMessage } from 'element-plus'
import type { UploadProps } from 'element-plus'
const showPercentage = ref(false)
const percentage = ref(0)
const props = defineProps({
action: {
type: String,
},
multiple: {
type: Boolean,
default: () => false,
},
showFileList: {
type: Boolean,
default: () => true,
},
drag: {
type: Boolean,
default: () => true,
},
accept: {
type: String,
},
limit: {
type: Number,
},
disabled: {
type: Boolean,
default: () => false,
},
autoUpload: {
type: Boolean,
default: () => true,
},
})
const getFileMd5 = (file: any) => {
return new Promise((resolve, reject) => {
const spark = new SparkMD5.ArrayBuffer()
console.log('spark', spark)
const fileReader = new FileReader()
console.log('fileReader', fileReader)
fileReader.onload = (e: any) => {
console.log('打印e', e)
spark.append(e.target.result)
resolve(spark.end())
}
fileReader.onerror = () => {
reject('')
}
fileReader.readAsArrayBuffer(file.file)
})
}
const getExtension = (file: File) => {
if (file) {
const regex = /(?:\.([^.]+))?$/
const result = regex.exec(file.name)
return result?.[1] || null
}
return null
}
const httpRequest = async (file: any) => {
ElMessage({
message: '开始上传,请等待!',
type: 'warning',
})
showPercentage.value = true
console.log('自定义上传了文件', file)
const fileMd5 = await getFileMd5(file)
console.log('打印文件的md5', fileMd5)
const fileGuid = newGuid()
console.log('打印生成的文件名称', fileGuid)
const fileSuffix = getExtension(file.file)
console.log('打印获取的文件后缀', fileSuffix)
const newFileName = fileGuid + '.' + fileSuffix
console.log('生成新文件名', newFileName)
let AccessKeyId = 'xxxx'
let AccessKeySecret = 'xxxx'
let res = await client(AccessKeyId, AccessKeySecret).multipartUpload(
newFileName,
file.file,
{
progress,
parallel: 4,
partSize: 1024 * 1024 * 1,
timeout: 120000,
}
)
console.log('打印上传的结果', res)
if (res.res.statusCode === 200) {
ElMessage({
message: '上传成功!',
type: 'success',
})
} else {
file.onError('上传失败')
}
}
const progress = (progress: any, checkpoint: any) => {
console.log('上传进度', progress)
percentage.value = progress.toFixed(2) * 100
console.log('分片上传的断点信息', checkpoint)
}
const beforeUpload: UploadProps['beforeUpload'] = (file) => {
console.log('上传文件之前的钩子函数', file)
}
const uploadFileProcess: UploadProps['onProgress'] = () => {
console.log('文件上传时的钩子函数')
}
const handleAvatarSuccess: UploadProps['onSuccess'] = (
response,
uploadFile
) => {
console.log('文件上传成功时的钩子')
setTimeout(() => {
showPercentage.value = false
percentage.value = 0
}, 300)
}
const handleRemove: UploadProps['onRemove'] = (file, uploadFiles) => {
console.log('文件列表移除文件时的钩子')
}
const handleExceed: UploadProps['onExceed'] = () => {
console.log('超出限制时,执行的钩子函数')
}
const handleChange: UploadProps['onChange'] = () => {
console.log('文件状态改变时的钩子函数')
}
script>
<style scoped lang="scss">style>
六、引入使用组件
const UploadFile = defineAsyncComponent(
() => import('@/components/uploadFile/index.vue')
)
<UploadFile></UploadFile>