前端大文件上传和下载(分片上传)

前端大文件上传和下载(分片上传)
一、问题
日常业务中难免出现前端需要向后端传输大型文件的情况,这时单次的请求不能满足传输大文件的需求,就需要用到分片上传
业务需求为:用户可以上传小于20G的镜像文件,并进显示当前上传进度
前端:vue3.x+Element Plus组件+axios
二、解决
解决思路简单为前端选择文件后读取到文件的基本信息,包括:文件的大小、文件格式等信息,用于前端校验,校验完成后将文件进行切片并通过请求轮询把切片传递给后端
Vue的元素代码如下,主要借助el-upload组件:
<template>
...
<!-- 文件上传 -->
<el-upload
:show-file-list="false"
action
class="mirror-upload"
:http-request="putinMirror"
>
<button>上传环境镜像</button>
</el-upload>
...
<!-- 进度显示 -->
<el-progress
:percentage="progress"
:indeterminate="true"
/>
...
</template>
<script setup>
// 引入封装好的接口api,根据提供的接口文档自行封装即可
import {
// 普通get请求api
checkMirrorFileApi,
// 普通post请求api
uploadShardFileApi,
} from "@/assets/api/uploadApi.js"
import { ref } from 'vue'
// 文件输进度条
const progress = ref(0)
...
</script>
1.第一步选择文件
配合组件选取需要上传的文件
/* 上传环境镜像 分片上传 */
const putinMirror = async (file) => {
// 校验文件是否符合规范(注意这里的异步方法,因为调用了接口加上await,校验函数若不调用接口可以不写await,否则返回promise对象)
if (await checkMirrorFile(file)) {
// 文件相关信息
let files = file.file
// 从0开始的切片
let shardIndex = 0
// 调用切片方法
uploadFile(files, shardIndex)
}
}
2.校验文件是否符合规范
这一步可以根据需求来进行校验,这里需要通过接口校验当前服务器可用的磁盘容量来判断是否有足够的空间用于存放将要上传的文件
/* 校验上传镜像文件是否符合规范 */
const checkMirrorFile = async (file) => {
// 校验文件格式是否正确,支持.acow2/.iso/.ovf/.zip/.tar
let fileType = file.file.name.split('.')
if (fileType[fileType.length - 1] !== 'acow2' && fileType[fileType.length - 1] !== 'iso' && fileType[fileType.length - 1] !== 'ovf' && fileType[fileType.length - 1] !== 'zip' && fileType[fileType.length - 1] !== 'tar') {
ElMessage.warning('文件格式错误,仅支持.acow2/.iso/.ovf/.zip/.tar')
return false
}
// 校验文件大小是否满足
let fileSize = file.file.size
//文件大小是否超出20G
if (fileSize > 20 * 1024 * 1024 * 1024) {
ElMessage.warning('上传文件大小不超过20G')
return false
}
const res = await checkMirrorFileApi()
if (res.code !== 200) {
ElMessage.warning('暂时无法查看磁盘可用空间,请重试')
return false
}
// 查看磁盘容量大小
if (res.data.diskDevInfos && res.data.diskDevInfos.length > 0) {
let saveSize = 0
res.data.diskDevInfos.forEach(i => {
// 磁盘空间赋值
if (i.devName === '/dev/mapper/centos-root') {
// 返回值为GB,转为字节B
saveSize = i.free * 1024 * 1024 * 1024
}
})
// 上传的文件大小没有超出磁盘可用空间
if (fileSize < saveSize) {
return true
} else {
ElMessage.warning('文件大小超出磁盘可用空间容量')
return false
}
} else {
ElMessage.warning('文件大小超出磁盘可用空间容量')
return false
}
}
3.文件切片上传
校验完成后就可以进行文件的切片上传了,这里用的类似接口轮询的方式,每次携带一个切片信息给后端,后端接受到切片并返回成功状态码后再进行下一次切片的上传,代码如下:
当然这里后端没有过多的做切片的处理,可以通过前端使用多线程,或者不等接口响应成功就进行下一次传递切片的过程进行上传的提速,这里具体怎么实现看业务需求或者怎么配合上传
/* 文件切片上传 */
const uploadFile = async (file, shardIndex, createTime, savePath, relativePath, timeMillis) => {
// 文件名
let name = file.name
// 文件大小
let size = file.size
// 分片大小
let shardSize = 1024 * 1024 * 5
// 分片总数
let shardTotal = Math.ceil(size / shardSize)
if (shardIndex >= shardTotal) {
isAlive.value = false
progress.value = 100
return
}
// 文件开始结束的位置
let start
前端大文件上传和下载(分片上传)
声明:除非特别标注,否则均为本站原创文章,转载时请以链接形式注明文章出处。如若本站内容侵犯了原著者的合法权益,可联系本站删除。



