当前位置: 首页 > news >正文

Vue中实现大文件的切片并发下载和下载进度展示

Vue中实现大文件的切片下载

切片下载需要后端提供两个接口,第一个接口用来获取当前下载文件的总切片数,第二个接口用来获取具体某一个切片的内容。

界面展示

在这里插入图片描述

数据流展示

在这里插入图片描述

代码

接口

// 切片下载-获取文件的总切片数
export function getChunkDownloadMetaInfo(queryParams) {
  return request({
    url: `/resource/chunkDownloadMetaInfoByUrl`,
    method: 'get',
    params: queryParams
  })
}

// 切片下载-获取当前切片的文件内容
export function getChunkDownload(queryParams) {
  return request({
    url: `/resource/chunkDownloadByUrl`,
    method: 'get',
    headers: {
      'Content-Type': 'application/json; application/octet-stream'
    },
    responseType: 'blob', //响应数据格式配置
    params: queryParams
  })
}

下载

// 下载
const downloadItem = async item => {
  const fileName = item.fileName
  const fileUrl = item.fileUrl
  if (item.isDownloading) {
    ElMessage({
      type: 'error',
      message: `${fileName}正在下载中请稍等`
    })
    return
  }
  item.progress = 0 // 下载进度
  item.isDownloading = true // 是否正在下载
  item.isAborted = false // 是否中止下载
  try {
    // 获取文件信息
    const fileInfo = await getFileInfo(fileUrl)
    const totalChunks = fileInfo.totalChunkNum

    // 并发下载所有切片
    const downloadedChunks = await downloadWithConcurrency(fileUrl, fileName, totalChunks, item)

    // 合并并下载文件
    const mergedBlob = mergeBlobs(downloadedChunks)
    triggerDownload(mergedBlob, fileName)
  } catch (error) {
    console.error('下载失败:', error)
    ElMessage({
      type: 'error',
      message: `${fileName}文件下载失败`
    })
  } finally {
    item.isDownloading = false
  }
}
// 获取文件信息
const getFileInfo = async fileUrl => {
  try {
    const response = await getChunkDownloadMetaInfo({ url: fileUrl })
    return response.data
  } catch (error) {
    throw new Error(`获取文件信息失败: ${error.message}`)
  }
}
// 下载单个切片
const downloadChunk = async (fileUrl, fileName, chunkIndex) => {
  try {
    const response = await getChunkDownload({
      url: fileUrl,
      chunkNumber: chunkIndex
    })
    return response
  } catch (error) {
    throw new Error(`下载切片失败: ${error.message}`)
  }
}
// 合并 Blob
const mergeBlobs = blobs => {
  return new Blob(blobs)
}
// 触发文件下载
const triggerDownload = (blob, fileName) => {
  const url = URL.createObjectURL(blob)
  const a = document.createElement('a')
  a.href = url
  a.download = fileName
  a.click()
  URL.revokeObjectURL(url)
}
// 并发下载
const downloadWithConcurrency = async (fileUrl, fileName, totalChunks, item) => {
  const downloadedChunks = new Array(totalChunks).fill(null)
  let completedChunks = 0

  const downloadNextChunk = async chunkIndex => {
    if (item.isAborted) return // 如果已中止,直接返回

    try {
      const chunk = await downloadChunk(fileUrl, fileName, chunkIndex)
      console.log(chunk, '123123123123123123')
      downloadedChunks[chunkIndex] = chunk

      // 更新下载进度
      completedChunks++
      item.progress = Math.round((completedChunks / totalChunks) * 100)
    } catch (error) {
      item.isAborted = true // 中止下载
      throw error
    }
  }

  // 启动并发下载
  const workers = []
  for (let i = 0; i < totalChunks; i++) {
    if (item.isAborted) break // 如果已中止,停止启动新任务

    if (workers.length >= maxConcurrency) {
      // 等待一个任务完成后再启动新任务
      await Promise.race(workers)
    }

    const worker = downloadNextChunk(i).finally(() => {
      workers.splice(workers.indexOf(worker), 1)
    })
    workers.push(worker)
  }

  await Promise.all(workers) // 等待所有任务完成
  return downloadedChunks
}

相关文章:

  • Spring Boot 的事务回滚
  • 【MySQL_02】安装(8.4.4LTS : Windows + Linux)
  • 在S32K3上实现SOC的神经网络算法的可行性
  • pyside6学习专栏(十):在PySide6中使用vtk模块绘制点、文本、线、三角形面、四面体、三棱柱、四棱锥等三维的基本元素对象
  • 多线程-线程本地变量ThreadLocal
  • Avalonia 中文乱码
  • C 语言数据结构(一):时/空间复制度
  • java环境部署
  • git修改本地用户名和邮箱和凭据
  • 171. Excel 表列序号
  • C++24--右值引用C++11新特性
  • 前端基础之组件自定义事件
  • Web服务器配置
  • PX4中的DroneCAN的实现库Libuavcan及基础功能示例
  • 利用行波展开法测量横观各向同性生物组织的生物力学特性|文献速递-医学影像人工智能进展
  • Web3 的未来:去中心化如何重塑互联网
  • 美颜SDK架构揭秘:人脸美型API的底层实现与优化策略
  • DeepSeek+Graphrag检索增强
  • 【0010】Python流程控制结构-分支结构详解
  • [machine learning] MACS、MACs、FLOPS、FLOPs
  • 中央宣传部、全国妇联联合发布2025年“最美家庭”
  • 基金经理调仓引发大金融板块拉升?公募新规落地究竟利好哪些板块
  • 泽连斯基:正在等待俄方确认参加会谈的代表团组成
  • 遭“特朗普关税”冲击,韩国今年经济增长预期“腰斩”降至0.8%
  • 秘鲁总理辞职
  • 习近平会见哥伦比亚总统佩特罗