You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

178 lines
4.7 KiB

<template>
<div class="flex justify-center items-center size-full">
<EdfsWrap title="固件上传" style="width: 50%; height: 50%">
<el-upload v-model:fileList="fileList" v-loading="loading" element-loading-text="上传中..." drag action=""
accept=".tar.gz" :limit="1" :on-exceed="handleExceed" :auto-upload="false" ref="uploadRef"
class="h-[calc(100%-30px)] w-full">
<div class="i-line-md:cloud-alt-upload-loop text-20px mx-auto"></div>
<div class="text">拖拽文件或者 <em>点击上传</em></div>
<template #tip v-if="!fileList.length">
<div class="el-upload__tip">上传限制一个文件,新文件会覆盖旧文件</div>
</template>
</el-upload>
<div class="flex justify-center">
<el-button type="primary" @click="onSave" v-show="fileList.length && !loading">确定上传</el-button>
<el-button type="info" v-show="loading" @click="onClone">取消上传</el-button>
</div>
</EdfsWrap>
</div>
</template>
<script setup lang="ts">
import { uploadFirmwareFile } from '@/api/module/firmware'
import { useMessage } from '@/composables/useMessage'
import type {
UploadInstance,
UploadProps,
UploadRawFile,
UploadUserFile,
} from 'element-plus'
const message = useMessage()
const fileList = ref<UploadUserFile[]>([])
const upload = ref<UploadInstance>()
const handleExceed: UploadProps['onExceed'] = files => {
upload.value!.clearFiles()
const file = files[0] as UploadRawFile
upload.value!.handleStart(file)
}
const uploadRef = ref<UploadInstance>()
const beforeAvatarUpload: UploadProps['beforeUpload'] = rawFile => {
const accept = ['.zip', '.tar', '.tar.gz']
const fileTypes = rawFile.name.substring(rawFile.name.indexOf('.'))
if (!accept.includes(fileTypes)) {
message.error('请上传 tar.gz 文件')
uploadRef.value?.clearFiles?.()
return false
}
return true
}
function validate() {
if (!fileList.value.length) {
message.error('请上传文件')
return true
}
return beforeAvatarUpload(fileList.value[0].raw!)
}
const loading = ref(false)
const abortController = ref<AbortController>()
async function onSave() {
if (loading.value) {
message.error('文件正在上传中,请稍后')
return
}
if (!validate()) return
loading.value = true
abortController.value = new AbortController()
const data = new FormData()
data.append('file', fileList.value[0].raw as File)
const userFile = fileList.value[0] as UploadUserFile
const res = await uploadFirmwareFile(data, abortController.value)
if (res.code === 0) {
message.success('上传成功')
} else {
message.error('上传失败')
}
// const file = userFile.raw as File
// const fileName = userFile.name
// const chunkList = await createChunksFromFileData(file, 1024)
// try {
// for (const chunk of chunkList) {
// const { chunkData, offset } = chunk
// const res = await uploadSftpFile(
// {
// fileName,
// chunk: chunkData,
// targetPath: props.curPath,
// offset,
// },
// abortController.value
// )
// if (res.code === -777) {
// return
// }
// if (![200, 0].includes(res.code)) {
// // 如果是手动取消的请求,不提示错误
// message.error(`上传失败,${res.msg}`)
// return
// }
// }
// } catch (error) {
// message.error('上传失败')
// }
abortController.value = undefined
loading.value = false
onClone()
}
async function readFileAsArrayBuffer(file: File): Promise<ArrayBuffer> {
return new Promise((resolve, reject) => {
const reader = new FileReader()
reader.readAsArrayBuffer(file)
reader.onload = () => resolve(reader.result as ArrayBuffer)
reader.onerror = reject
})
}
async function createChunksFromFileData(file: File, chunkSize: number) {
const fileData = await readFileAsArrayBuffer(file)
const chunkList: { offset: number; chunkIndex: number; chunkData: Uint8Array }[] = []
let offset = 0
let chunkIndex = 0
while (offset < fileData.byteLength) {
const chunkData = new Uint8Array(fileData.slice(offset, offset + chunkSize))
chunkList.push({
offset,
chunkIndex,
chunkData,
})
offset += chunkSize
chunkIndex++
}
return chunkList
}
function clearData() {
fileList.value = []
}
function onClone() {
if (loading.value) {
abortController.value?.abort()
loading.value = false
}
clearData()
}
</script>
<style lang="scss" scoped>
:deep(.el-upload) {
height: calc(100% - 50px);
width: 100%;
}
:deep(.el-upload-dragger) {
height: 100%;
width: 100%;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
</style>