前端之大文件断点上传

@1 前端如何上传大文件呢? 接下来我们模拟前端上传大文件的操作。首先需要安装axios和spark-md5这两个插件。
        1 定义一个input 类型为file的标签,给标签绑定事件。image图片 标签,以及一个total全局常
        量的进度条,定义断点续传的变量 let isupload = false ; var total = 0;   
        <input type="file" @change="changeFile" />   <image src="image">  <video src="" />
        2 文件在上传的过程中一般会采用 二进制 base64 buffer格式的。如果是图片的一般采用
        base64格式的。
        3 首先我们定义一个方法以什么格式读取文件。第一个参数为上传的文件,第二个参数格式。
         const fileParse(file, type='base64') {
                return new Promise(resolve=>{
                      const fileRead =   new FileReader() // 主要是用来new读取文件的实例化对香
                      if(type==='base64') { // 进行判断需要转为什么格式的文件
                                 fileRead.readAsDataURL(file) // 转为base64格式的
                        }else if(type==='buffer') {
                                fileRead.readAsArrayBuffer(file) // 转为Buffer格式的
                        }
                        fileRead.onload(e=>{
                                resolve(e.target.result) // 文件转化成功后的回调函数
                        })
                })
        }
        4 这时候我们开始选择文件进行上传 触发changeFile这个方法 先上传图片
        async changeFile (file) {
                if(! file) return 
                file = file.target.files[0] //  获取上传的图片 
                const res = await fileParse(file,'base64') // 调用3封装的方法读取文件 转为base64
                result = await axios.post('/uploadImage', qs.stringfy({
                        chunk:encodeURLComponent(res) // 上传文件的参数 base64编码
                        filename:file.name // 文件的名称
                 }),{
                       headers:{
                                “Content-Type”:“application/x-www-form-urlencoded”
                        }
                  })
                result = result.data // 获取上传成功后的数据
                document.queryselector('image').src = result.path // 将获取的图片路径赋值给图片标
        }
        5 选择大文件进行切片上传: 思路将大文件进行分片上传 上传成功后进行合并 
        async changeFile (file) {
                if(!file) return 
                file = file.target.files[0] // 获取上传的文件 
                // 第一步将上传的文件解析为buffer数据 调用上面封装的方法
                const res = await fileParse(file,‘buffer’)
                spark = new SparkMD5.ArrayBuffer() // 使用sparkMD5这个第三方插件生成hsah值
                hash,  // 定义hash值
                suffix, // 定义后缀名 格式
                spark.append(res);
                hash = spark.end() // 获取hash值
                suffix = /\.([0-9a-zA-Z]+)$/i.exec(file.name)[1] // 获取文件格式
                // 第二步 创建切片
                let parList = [ ] // 切片的集合
                partsize = file.size / 100  // 定义每个切片的大小 给切片设置100份
                cur = 0; 切片的起始值
                for(let i = 0; i < 100; i++){
                        let item = {
                                chunk:file.slice(cur,cur+partsize), // 每个切片
                                filename:`${hash}_${i}.${suffix}` // 切片的名称 hash-1.mp4 格式的
                        }
                        cur+=partsize // 重新计算起始值
                        parList.push(item) // 所有的切片集合
                }
                this.hash = hash // 给全局的hash和parList赋值方便下面方法的获取
                this.parList = parList 
                this.sendRequest() // 调用上传切片的方法
                }
                // 第三步 定义切片上传的方法
                async sendRequest() {
                        // 创建100个切片上传的集合 
                        const requestList = [ ]
                        this.parList.forEach( (item ,index) = > {
                                let fn = ()=>{
                                        let formData = new FormData()
                                        formData.append('chunk',item.chunk)
                                        formData.append('filename',item.name)
                                        return axios.post('/upload',formData,{
                                                headers:{'Content-Type':'multipart/form-data'}
                                        }).then(res=>{
                                                res = res.data
                                                if(res.code===0){
                                                        this.total+=1  // 这个total可以在全局定义为0 定义进度条
                                                        this.parList.splice(index,i) // 将上传完的切片移除,后期继续上
                                                        传的话就不会重复上传已经上传完成的切片了
                                                }
                                        })
                                }
                                requeList.push(fn) 
                        })
                        let i = 0;  //定义的i用来记录切片上传了多少个
                        let compte = async ()=>{  // 定义切片上传完成后 合并切片请求的方法
                                let result = await axios.get('/merge',{
                                        hash:this.hash
                                 })
                                res = resullt.data
                                 this.video = result.path // 服务器返回上传文件的地址进行赋值,这里用的是
                                视频
                        }
                        // 递归函数执行 上传切片
                        let send = async ()=>{
                               if(isupload) return   //利用isupload这个变量在这里控制文件是否继续上传
                                if(i>=requeList.length) {
                                 // 上传完了 需要调用合并切片的请求了
                                 complete()
                                 return 
                                }
                                await requeList[i]() // 执行每一个切片上传的方法
                                i++;
                                send()
                        }
                        send()
                }
                第四步断点续传:可以给两个按钮控制isupload值得变化,重新调用方法
                <button @click="stop">暂停</button>  <button @click="start">继续</button>
                stop(){
                this.isupload = true
                this.sendRequest() // 再次调用切片上传的方法
                },
                start() { this.isupload = false;this.sendRequest() }
        
        

  • 7
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值