断点续传组件

<template>
  <div id="app">
    <!-- 上传组件 -->
    <el-upload action drag :auto-upload="false" :show-file-list="false" :on-change="handleChange">
      <i class="el-icon-upload"></i>
      <div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
      <div class="el-upload__tip" slot="tip">大小不超过 200M 的视频</div>
    </el-upload>

    <!-- 进度显示 -->
    <div class="progress-box">
      <span>上传进度:{{ percent.toFixed() }}%</span>
      <el-button type="primary" size="mini" @click="handleClickBtn">{{ upload | btnTextFilter}}</el-button>
    </div>

    <!-- 展示上传成功的视频 -->
    <div v-if="videoUrl">
      <video :src="videoUrl" controls />
    </div>
  </div>
</template>

<script>
  import SparkMD5 from "spark-md5"
  import axios from "axios"
  
  export default {
    name: 'App3',
    filters: {
      btnTextFilter(val) {
        return val ? '暂停' : '继续'
      }
    },
    data() {
      return {
        percent: 0,
        videoUrl: '',
        upload: true,
        percentCount: 0
      }
    },
    methods: {
      async handleChange(file) {
        if (!file) return
        this.percent = 0
        this.videoUrl = ''
        // 获取文件并转成 ArrayBuffer 对象
        const fileObj = file.raw
        let buffer
        try {
          buffer = await this.fileToBuffer(fileObj)
        } catch (e) {
          console.log(e)
        }
        
        // 将文件按固定大小(2M)进行切片,注意此处同时声明了多个常量
        const chunkSize = 2097152,
          chunkList = [], // 保存所有切片的数组
          chunkListLength = Math.ceil(fileObj.size / chunkSize), // 计算总共多个切片
          suffix = /\.([0-9A-z]+)$/.exec(fileObj.name)[1] // 文件后缀名
          
        // 根据文件内容生成 hash 值
        const spark = new SparkMD5.ArrayBuffer()
        spark.append(buffer)
        const hash = spark.end()

        // 生成切片,这里后端要求传递的参数为字节数据块(chunk)和每个数据块的文件名(fileName)
        let curChunk = 0 // 切片时的初始位置
        for (let i = 0; i < chunkListLength; i++) {
          const item = {
            chunk: fileObj.slice(curChunk, curChunk + chunkSize),
            fileName: `${hash}_${i}.${suffix}` // 文件名规则按照 hash_1.jpg 命名
          }
          curChunk += chunkSize
          chunkList.push(item)
        }
        this.chunkList = chunkList // sendRequest 要用到
        this.hash = hash // sendRequest 要用到
        this.sendRequest()
      },
      
      // 发送请求
      sendRequest() {
        const requestList = [] // 请求集合
        this.chunkList.forEach((item, index) => {
          const fn = () => {
            const formData = new FormData()
            formData.append('chunk', item.chunk)
            formData.append('filename', item.fileName)
            return axios({
              url: '/single3',
              method: 'post',
              headers: { 'Content-Type': 'multipart/form-data' },
              data: formData
            }).then(res => {
              if (res.data.code === 0) { // 成功
                if (this.percentCount === 0) { // 避免上传成功后会删除切片改变 chunkList 的长度影响到 percentCount 的值
                  this.percentCount = 100 / this.chunkList.length
                }
                this.percent += this.percentCount // 改变进度
                this.chunkList.splice(index, 1) // 一旦上传成功就删除这一个 chunk,方便断点续传
              }
            })
          }
          requestList.push(fn)
        })
        
        let i = 0 // 记录发送的请求个数
        // 文件切片全部发送完毕后,需要请求 '/merge' 接口,把文件的 hash 传递给服务器
        const complete = () => {
          axios({
            url: '/merge',
            method: 'get',
            params: { hash: this.hash }
          }).then(res => {
            if (res.data.code === 0) { // 请求发送成功
              this.videoUrl = res.data.path
            }
          })
        }
        const send = async () => {
          if (!this.upload) return
          if (i >= requestList.length) {
            // 发送完毕
            complete()
            return
          } 
          await requestList[i]()
          i++
          send()
        }
        send() // 发送请求
      },
      
      // 按下暂停按钮
      handleClickBtn() {
        this.upload = !this.upload
        // 如果不暂停则继续上传
        if (this.upload) this.sendRequest()
      },
      
      // 将 File 对象转为 ArrayBuffer 
      fileToBuffer(file) {
        return new Promise((resolve, reject) => {
          const fr = new FileReader()
          fr.onload = e => {
            resolve(e.target.result)
          }
          fr.readAsArrayBuffer(file)
          fr.onerror = () => {
            reject(new Error('转换文件格式发生错误'))
          }
        })
      }
    }
  }
</script>

<style scoped>
  .progress-box {
    box-sizing: border-box;
    width: 360px;
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-top: 10px;
    padding: 8px 10px;
    background-color: #ecf5ff;
    font-size: 14px;
    border-radius: 4px;
  }
</style>


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
现在大部分的网站使用的是标准HTML的上传方式来上传文件。一般情况下标准HTML方式在网页中只能上传4MB左右的文件,如果访问的用户比较多的时侯这种方式容易上传失败。虽然标准HTML上传方式开发起来比较简单,但是这种方式用户体验比较差,上传的文件大小受到限制,所以如果我们需要上传上百或者更大的上G的文件时,HTML标准上传方式是无法满足我们的需求的。 而另一方面,随着互联网行业的发展用户产生的新的需求也越来越多,同时对用户体验也提出了更高的要求,传统的HTML方式也越来越难已满足新的用户需求。现在大部分的用户有文件批量上传的需求,希望只通过点击一次鼠标就能够批量的上传多张图片,而不是一张张的选择文件上传,这样操作即浪费时间又非常烦琐。 近年来,由于数码和影视行业的迅猛发展刺激了用户对大文件的上传需求,现在越来越多的用户希望能够通过WEB的方式上传更大的文件,比如电影和图片。这些类型的文件通常都非常大,一般都在500MB以上,高清的影视文件至少在1G以上。这样的大文件是根本无法通过标准HTML方式来上传的。 不仅如此,由于国内网络环境比较特殊,有许多地区的网络不够稳定,在上传文件的过程中可能会发生断网的情况。如果用户正在上传一个1000MB的文件,已经上传了500MB,这时网络出现问题上传中止了。那么下一次用户需要要重新上传前面的500MB,而不是从500MB开始上传,这将浪费用户的许多时间。 新颖网络HTTP文件断点续传控件是专门用于解决HTTP大文件上传的需求而开发的产品。通过我们的HttpPartition模块用户能够非常方便的一次性选择超过200个的文件。而且我们升级了用户体验,用户现在不仅能够通过点击按钮来选择多个文件,还可以通过HttpDroper来拖拽文件甚至是文件夹。 现在我们能够轻松支持2G左右的大文件上传。为了减轻服务器的压力在HttpUploader模块中我们并不是一次上传2G的数据,而是将2G化分为小的数据块,每次向服务器上传约128KB左右的数据。同时在每次上传的数据中附带了文件大小,起始位置,文件MD5等信息。对于开发人员来说,有了这些信息,断点续传功能将会变的和普通的文件上传功能一样简单。 相信新颖网络HTTP断点续传控件能够帮助您赢利市场。 产品介绍:[url=http://www.cnblogs.com/xproer/archive/2012/02/17/2355440.html][/url]
点量Http、FTP多线程断点续传下载组件(下载DLL)的开发目的是让用户可以无需关心Http/FTP协议的具体细节,只需要几十行甚至几行代码,便可以实现一个功能完善的Http/FTP下载软件。点量Http/FTP下载组件(DLL)支持多线程、断点续传、显示详细下载过程、自动查找镜像网址、支持代理传输等完善的功能。 点量Http、FTP下载内核源码使用高效的c++代码编写,提供标准的动态链接库(DLL),可供C/C++、Delphi、C#、Java、VB等语言和各常用开发环境调用,让您完全像调用系统API一样的调用。 点量Http/FTP组件的功能简介: 标准Http和FTP下载支持:完全标准的Http和FTP协议支持,内部通过网址自动区分是Http还是FTP下载。 极速下载(2.0以后版本):超越国内绝大多数下载软件的下载速度。新版内核在2M ADSL的环境下下载,有些文件的速度可以达到1400K字节/秒以上,超过了带宽的极限。下载速度可以用极速形容。 多线程传输:可以将文件自动分块,并采用多线程下载。并可自由设置线程数目。 断点续传:点量Http/FTP有优秀的断点续传支持,每次启动自动从上次下载的位置开始,不需要重复下载。 提供详细的下载详情接口(2.0以后版本):可以看到整个下载过程的步骤,比如开启了多少线程、服务器的应答过程、错误信息等。 支持多种高级设置:设置线程数目、磁盘缓存大小、搜索镜像服务器的详细参数设置、下载文件完成后同步文件为服务器上的文件时间、下载过程中可以自定义文件临时后缀、未完成的文件设为隐藏属性。 支持磁盘缓存:点量Http/FTP下载DLL支持设置磁盘缓存,减少对磁盘的读写,并提升下载速度。 支持设置Refer:点量Http/FTP下载组件支持设置下载时的Refer,以便可以绕过一些防盗链的网站,直接下载内容。 限速功能:点量Http/FTP下载组件可方便的设置下载限速。 多种磁盘分配方式:点量Http/FTP下载组件支持预分配和边下载边分配两种磁盘方式,满足多种下载需求。 自动搜索镜像加速:点量Http/FTP内置了镜像搜索功能,在下载文件的同时,会自动搜索哪些其它网站还有这个文件,自动从其它网址下载加速。 可提供源码:支付一定的费用,便可以获得全部的点量Http/FTP下载组件的源代码,免除您的所有后顾之忧。 良好的服务:作为点量软件旗下的软件,可享受到点量软件的优秀服务,我们的服务让您如同拥有一个称心的专业员工。 点量Http/FTP 下载组件可以适用于任何Http和FTP下载的领域,让您可以在1天内完成一个完整的Http下载软件的全部功能。比如,您可以用于产品的升级、文件的下载和传输等。
现在大部分的网站使用的是标准HTML的上传方式来上传文件。一般情况下标准HTML方式在网页中只能上传4MB左右的文件,如果访问的用户比较多的时侯这种方式容易上传失败。虽然标准HTML上传方式开发起来比较简单,但是这种方式用户体验比较差,上传的文件大小受到限制,所以如果我们需要上传上百或者更大的上G的文件时,HTML标准上传方式是无法满足我们的需求的。 而另一方面,随着互联网行业的发展用户产生的新的需求也越来越多,同时对用户体验也提出了更高的要求,传统的HTML方式也越来越难已满足新的用户需求。现在大部分的用户有文件批量上传的需求,希望只通过点击一次鼠标就能够批量的上传多张图片,而不是一张张的选择文件上传,这样操作即浪费时间又非常烦琐。 近年来,由于数码和影视行业的迅猛发展刺激了用户对大文件的上传需求,现在越来越多的用户希望能够通过WEB的方式上传更大的文件,比如电影和图片。这些类型的文件通常都非常大,一般都在500MB以上,高清的影视文件至少在1G以上。这样的大文件是根本无法通过标准HTML方式来上传的。 不仅如此,由于国内网络环境比较特殊,有许多地区的网络不够稳定,在上传文件的过程中可能会发生断网的情况。如果用户正在上传一个1000MB的文件,已经上传了500MB,这时网络出现问题上传中止了。那么下一次用户需要要重新上传前面的500MB,而不是从500MB开始上传,这将浪费用户的许多时间。 新颖网络HTTP文件断点续传控件是专门用于解决HTTP大文件上传的需求而开发的产品。通过我们的HttpPartition模块用户能够非常方便的一次性选择超过200个的文件。而且我们升级了用户体验,用户现在不仅能够通过点击按钮来选择多个文件,还可以通过HttpDroper来拖拽文件甚至是文件夹。 现在我们能够轻松支持2G左右的大文件上传。为了减轻服务器的压力在HttpUploader模块中我们并不是一次上传2G的数据,而是将2G化分为小的数据块,每次向服务器上传约128KB左右的数据。同时在每次上传的数据中附带了文件大小,起始位置,文件MD5等信息。对于开发人员来说,有了这些信息,断点续传功能将会变的和普通的文件上传功能一样简单。 相信新颖网络HTTP断点续传控件能够帮助您赢利市场。 版权所有 2009-2012 北京新颖网络 保留所有权利 官方网站:http://www.ncmem.com/ 产品首页:http://www.ncmem.com/webplug/http-uploader3/index.aspx 在线演示:http://www.ncmem.com/products/http-uploader/demo/index.html 产品介绍:http://www.cnblogs.com/xproer/archive/2012/02/17/2355440.html 开发文档-ASP:http://www.cnblogs.com/xproer/archive/2012/02/17/2355458.html 开发文档-PHP:http://www.cnblogs.com/xproer/archive/2012/02/17/2355467.html 开发文档-JSP:http://www.cnblogs.com/xproer/archive/2012/02/17/2355462.html 开发文档-ASP.NET:http://www.cnblogs.com/xproer/archive/2012/02/17/2355469.html 升级日志:http://www.cnblogs.com/xproer/archive/2012/02/17/2355449.html 示例下载:http://www.ncmem.com/download/HttpUploader3-demo.rar 文档下载:http://www.ncmem.com/download/HttpUploader3-doc.rar 问题反馈:http://www.ncmem.com/blog/guestbook.asp Windows数字证书补丁:http://www.ncmem.com/download/rootsupd.rar Microsoft Visual C++ 2008 Redistributable Package (x86):http://www.microsoft.com/download/en/details.aspx?displaylang=en&id=29
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值