在开发中,如果上传的文件过大,可以考虑分片上传,分片就是说将文件拆分来进行上传,将各个文件的切片传递给后台,然后后台再进行合并。这里切片可以理解为字符串的截取,那这里文件的话就是切分字节,一个道理

上传的时候,可能会需要一个文件的唯一 标识,在上传文件的时候也要将文件的唯一标识(文件的MD5加密文件的字符串,每个文件的唯一标识)传递给后端,后端会通过该标识返回给我们告诉我们这个文件是否已经上传过,没有这个文件就需要我们全部上传,存在了,前端就不需要再上传,这个文件上传了一部分,需要把剩余的上传

这个文件的MD5唯一标识呢,也是通过spark-md5来获取,具体步骤 :

安装 

npm i spark-md5
or
pnpm add spark-md5

按需引入 ,并封装方法

可以单独建个js文件,向外暴露出去 

method.js 

import SparkMD5 from 'spark-md5'

// 获取文件的唯一MD5标识码
export function getFileMd5(file) {
return new Promise((resolve, reject) => {
const fileReader = new FileReader()
const spark = new SparkMD5.ArrayBuffer()
fileReader.readAsArrayBuffer(file)
fileReader.onload = e => {
spark.append(e.target.result)
let md5 = spark.end()
resolve(md5)
}
})
}

然后我们提交的时候,我们得让后台知道提交的是哪一部分的切片,不能驴头不对马嘴,闲话不多说了,我这里把核心代码贴上,大家有点儿基础的,仔细看下就懂得了,没有很复杂 

我这里用的是Vue3 + element-plus中的el-upload 

<div class="index">
<el-upload
v-model:file-list="fileList"
class="upload-demo"
:auto-upload="false"
:limit="1"
:on-change="handleChange"
>
<el-button type="primary">Click to upload</el-button>
</el-upload>
</div>
<script setup>
import { ref } from 'vue'
import { getFileMd5 } from './method'

const fileList = ref([])

// 文件上传 选择文件时触发(:on-change事件)
const handleChange = async (uploadFile, uploadFiles) => {
// 文件信息
let fileRaw = uploadFile.raw
console.log(fileRaw)
// 获取 文件的 MD5唯一标识码
let fileMd5 = null
try {
fileMd5 = await getFileMd5(fileRaw)
} catch(e) {
console.error('[error]', e)
}
if(!fileMd5) return
// 每片的大小为 5M 可调整
const chunkSize = 5 * 1024 * 1024
// 文件分片储存
let chunkList = []
function chunkPush(page = 1) {
chunkList.push(fileRaw.slice((page - 1) * chunkSize, page * chunkSize))
if(page * chunkSize < fileRaw.size) {
chunkPush(page + 1)
}
}
chunkPush()
console.log(chunkList, 'chunkList----->>>')
saveFileChunk(chunkList, fileMd5, fileRaw.name)
}
// 保存文件片段到后台
const saveFileChunk = async (chunkList, fileMd5, fileName) => {
for(let i = 0; i < chunkList.length; i++) {
let formData = new FormData()
formData.append('chunk', i) // 当前片段的索引
formData.append('chunkSize', 5 * 1024 * 1024) // 切片的文件分片大小 (就是以多少字节进行分片的,这里是5M)
formData.append('chunks', chunkList.length) // 共有多少分片
formData.append('file', chunkList[i]) // 当前分片的文件流
formData.append('md5', fileMd5) // 整个文件的MD5唯一标识码,不是分片
formData.append('name', fileName) // 文件的名称
formData.append('size', chunkList[i].size) // 当前切片的大小(最后一片不一定是5M)
const data = await saveFileChunk(formData)
if(data && data.success) {
console.log('保存成功')
}
}
}
</script>

灵感来自:​​# vue 实现文件切上传​​