分片上传与断点续传

分片上传与断点续传

Github仓库完整代码

效果

请添加图片描述

采用在线编辑 cloudstudio

初始化

  • npm i init
  • npm i express
  • npm i express-fileupload
  • npm i axios
  • npm i crypto-js

为何断点续传

  • 浏览器对文件大小限制
  • 上传失败后重新传送
  • 中断传送后再次传送

实现思路

前端

  1. 拿到文件,对文件进行读取操作
function read(file){
    
    

  const reader=new FileReader()
  return new Promise(((resolve, reject) => {
    
    
    reader.onload=function (){
    
     // 读取成功返回
      resolve(reader.result)
    }
    reader.onerror=reject // 失败返回
    reader.readAsBinaryString(file) // 返回读取的字符串
  }))
}
  1. MD5加密
  const hash=CryptoJS.MD5(content)
  1. 对文件进行分片操作
 while (uploaded<size){
    
    
    const chunk=file.slice(uploaded,uploaded+chunkSize,type) // file继承自blod,blod有方法slice,可对文件进行切片处理
    const formData=new FormData()
    formData.append('name',name)
    formData.append('type',type)
    formData.append('size',size)
    formData.append('hash',hash)
    formData.append('file',chunk)
    formData.append('offset',uploaded)
    formData.append('index',index)
    axiosArr.push(formData)
    index+=1
    uploaded +=chunk.size


  }
  1. 判断这个文件是否上传过(也就是上传到一半中止了)
  const local=localStorage.getItem(hash)
  1. 从当前地方继续上传
const newDoneArr=[]
    isDoneArr.map((item,index)=>{
    
    
      if(item===0){
    
    
        newDoneArr.push(axiosArr[index])
      }
    })
    progress.max=newDoneArr.length-1
    progress.value=0
    multiRequest(newDoneArr,1)
  1. 开始上传,加入待上传队列中
function enqueue(queue=[],url){
    
    
    const len=queue.push(url)  // 加入队列中
    request(queue,url) // 请求开始
    return len
  }
  1. 请求成功,修改状态数据
	const result=await axios.post('/api/upload',formData)
    const i=urlsClone.indexOf(formData) // 上传的是哪个文件
    const hash=formData.get('hash') // 拿到hash标识
    localStorage.setItem(hash,i)// 保存上传的状态
    result[i]=formData
    isDoneArr[i]=1 // 修改状态数据为完成
  1. 判定是否上传完成
function dequeue(queue=[],formData){
    
    
    progress.value += 1 // 当前上传到哪了
    queue.splice(queue.indexOf(formData),1) // 从queue中移除已完成请求
    if(uls.length){
    
     // 如果还有未上传文件,继续上传
      enqueue(queue,uls.shift())
    }else {
    
     // 上传完成给出提示
      if(isDoneArr.indexOf(0)===-1){
    
    
        output.innerText='上传成功'
        progress.value=urlsClone.length
        localStorage.removeItem(formData.get('hash'))
      }
    }
  }

后端

  1. 利用FS模块向文件中写入数据
  2. 先解析出文件名
const {
    
    name, type, size, offset, hash,index} = req.body
  1. 写入文件
 await appendFile(filename, file.data) 

猜你喜欢

转载自blog.csdn.net/weixin_64925940/article/details/125457266