首页 > 其他分享 >js 大文件切片,中止上传,上传进度,断点续传

js 大文件切片,中止上传,上传进度,断点续传

时间:2023-11-24 10:32:55浏览次数:38  
标签:断点续传 const await js 切片 file 服务器 上传

大文件切片上传
背景介绍:当涉及大文件上传时,一种有效的方法是将大文件分割成小切片并逐个上传。这种技术不仅可以减轻服务器的负担,还可以避免上传过程中的中断和内存问题。本文将介绍如何使用JavaScript实现大文件切片上传,并解释如何处理断点续传、并发控制以及上传取消等问题,用到的知识点有大文件切片、中止上传 、上传进度、断点续传、并发数量控制。

切片上传原理
大文件切片上传的基本原理是将文件分成多个固定大小的小切片,然后逐个上传到服务器。服务器收到这些切片后,可以按顺序合并它们,还原为完整的文件。这种方法不仅能提高上传效率,还能应对网络波动和服务器性能限制。

实现步骤
下面是实现大文件切片上传的基本步骤:

切片生成: 使用JavaScript将大文件切割成小切片,可以使用File API中的File.slice()方法。

切片上传: 将切片逐个上传到服务器,可以使用XMLHttpRequest或Fetch API发送切片数据。

服务器处理: 服务器接收并保存切片,并记录每个切片的索引。

切片合并: 当所有切片上传完成后,服务器按照索引顺序合并切片(或者后端提供合并接口将hash值传给后端进行合并),还原为完整文件。

断点续传
通过记录已上传切片的索引,即使上传过程中断,也可以从断点处继续上传。服务器只需判断已存在的切片,避免重新上传。

并发控制
为了避免同时上传大量切片导致网络拥塞,可以控制并发上传数。例如,一次最多只上传3个切片,等待其中一个完成后再上传下一个。

上传取消
允许用户在上传过程中取消操作是很重要的。为此,可以使用一个标记来判断是否取消上传,如果取消,则终止上传过程。

接下来,我们将深入探讨如何在JavaScript中实现这些功能。从切片生成和上传开始,逐步讲解如何处理断点续传、并发控制和上传取消。

话不多说,上代码

<template>
  <div class="manage">
    <input type="file" @change="handleFileChange" multiple />
    <button @click="stop">停止上传</button>
    <span>当前已上传:{{progress}}%</span>
  </div>
</template><script>
export default {
  name: 'Menu',
  props: {
  },
  mounted () {
  },
  data () {
    return {
      progress: 0,
      stopUpload: false,
      totalChunks: null,
      selectedFiles: [],
      uploadPromises: [],
      concurrentLimit: 2 // 控制并发数量
    }
  },
  methods: {
    handleFileChange (event) {
      this.selectedFiles = Array.from(event.target.files)
      this.startUpload(event.target.files)
    },
    async uploadFile (file, index, total) {
      return new Promise((resolve, reject) => {
        // 模拟上传操作,实际上传操作可能需要使用 XMLHttpRequest 或其他上传库
        // setTimeout(async () => {
        //   console.log(`Uploaded: ${file.name}`)
        //   const formData = new FormData();
        //   formData.append('fileChunk', file);
        //   formData.append('chunkIndex', index);
        //   formData.append('totalChunks', total);
        //   const response = await fetch('upload-url', {
        //     method: 'POST',
        //     body: formData
        //   });
        //   const result = await response.json();
        //   resolve(result)
        // }, 1000) // 假设上传耗时 1 秒
        setTimeout(async () => {
          console.log(`Uploaded: ${file.name}`)
          resolve()
        }, 2000) // 假设上传耗时 1 秒
      })
    },
    async startUpload (file) {
      console.log('file', file)
      this.uploadPromises = []
      const size = 1024 * 1024
      const formNum = Math.ceil(file[0].size / size)
      const hashes = []
      for (let i = 0; i <= formNum; i++) {
        const start = size * i;
        const end = size * (i + 1)
        const chunk = file[0].slice(start, end);
        const hash = await this.calculateHash(chunk);
        console.log('this.stopUpload', this.stopUpload)
        if (this.stopUpload) return false
        hashes.push(hash)
        // 将需要上传的切片和对应的哈希值添加到FormData中
        // 断点续传逻辑需要后端判断,前端根据片段生成唯一hash值,后端存储hash,续传时候需要判断若已上传直接给出进度
        const promise = this.uploadFile(chunk, i, formNum)
        this.uploadPromises.push(promise)        if (this.uploadPromises.length >= this.concurrentLimit) {
          await Promise.race(this.uploadPromises) // 控制并发
          this.uploadPromises.shift() // 移除已完成的 Promise
        }
        this.progress = (i / formNum) * 100
      }
      console.log('hashes', hashes)
      await Promise.all(this.uploadPromises) // 等待剩余的上传完成
      console.log('全部完成上传!')
      // 调用后端提供合并接口
      // const response = await fetch('upload-merge', {
      //   method: 'POST',
      //   body: hashes
      // })
    },
    async calculateHash (chunk) {
      const buffer = await chunk.arrayBuffer()
      const hashBuffer = await crypto.subtle.digest('SHA-256', buffer)
      const hashArray = Array.from(new Uint8Array(hashBuffer))
      const hashHex = hashArray.map(byte => byte.toString(16).padStart(2, '0')).join('')
      return hashHex
    },
    stop () {
      this.stopUpload = true
    }
  }
}
</script>


参考文章:http://blog.ncmem.com/wordpress/2023/10/21/js-大文件切片,中止上传,上传进度,断点续传/


 

标签:断点续传,const,await,js,切片,file,服务器,上传
From: https://blog.51cto.com/u_14023400/8545001

相关文章

  • 基于JS的大文件分片
    项目需要上传超大文件,后台为DJANGO,不能直接用H5的FILEAPI来POST,所以采用slice分片在分片后为BLOB不能直接传,bolb转file有些浏览器又有支持问题。所以做一些转换,转uint8,uint16,uint32,django的后台处理起来都比较烦所以试着用base64装入json,很容易搞定。具体思路:1.读入文件路径2.按......
  • 详解vue大文件视频切片上传的处理方法
    前端上传大文件、视频的时候会出现超时、过大、很慢等情况,为了解决这一问题,跟后端配合做了一个切片的功能,接下来就详细的给大家介绍一下vue大文件视频切片上传的处理方法,需要的朋友可以参考下 前端上传大文件、视频的时候会出现超时、过大、很慢等情况,为了解决这一问题,跟后端......
  • java实现大文件的分片上传与下载(springboot+vue3)
    1.1项目背景对于超大文件上传我们可能遇到以下问题•大文件直接上传,占用过多内存,可能导致内存溢出甚至系统崩溃•受网络环境影响,可能导致传输中断,只能重新传输•传输时间长,用户无法知道传输进度,用户体验不佳1.2项目目标对于上述问题,我们需要对文件做分片传输。分片传输就是......
  • Extjs应用tab页的最简单Demo
    <html><head><title>Extjs应用tab页的最简单Demo</title><linkrel="stylesheet"type="text/css"href="theme-gray-all.css"/><scripttype="text/javascript"src="ext-all.js"><......
  • js 全局变量
    1、赋值并保存import{setSessionStorage}from'@/store/index' Vue.prototype.$userId=res.result.userInfo.idVue.prototype.$userType=res.result.userInfo.postsetSessionStorage()2、index.jsexportfunctionsetSessionStorage(){varstore={......
  • .Net Core MVC超大文件上传
    后端控制器://用于保存的文件夹staticreadonlystringuploadFolder="UploadFolder";//目录分隔符,兼容不同系统staticreadonlychardirSeparator=Path.DirectorySeparatorChar;stringGetTmpChunkDir(stringfileName)=>HttpContext.Session.TryGet......
  • js 优化
    提炼函数把条件分支语句提炼成函数合理使用循环提前让函数退出代替嵌套条件分支传递对象参数代替过长的参数列表少用三目运算符合理使用链式调用分解大型类活用位操作符纯函数(1).提炼函数:①.避免超大函数.②.独立出来的函数有助于代码复用.③.独立出来的函数更容......
  • postman 出现Enable JavaScript and cookies to continue 如何反爬(js反爬)
    网页无法F12,禁止调试出现debug怎么办直接F8禁用,ctrl+F8开启调试断点网站禁止ip访问,并且关闭了icmp回包,调试最好禁用缓存,以便实时更新用postman单独访问首页的index的首页也是无法获取网页内容考虑网页使用js进行跳转实例:比如使用postman请求https://www.phind.com/简......
  • Springboot文件上传代码笔记
    1.在src下创建filter包,包内Class名UploadFilterpackagecom.gd.filter;importorg.apache.catalina.servlet4preview.http.HttpServletRequest;importjavax.servlet.*;importjavax.servlet.annotation.WebFilter;importjavax.servlet.http.HttpServletResponse;impor......
  • js关系运算符
    关系运算符:==等于>大于<小于>=大于等于<=小于等于!=不等于===全等例子:等于: 大于: 小于: 大于等于: 小于等于: 不等于: //全等 //全等和等于的区别://==在js中,只是对值,进行比较......