vue实现大文件分片上传与断点续传到七牛云

问题:

前段时间做视频上传业务,通过网页上传视频到服务器。

视频大小 小则几十M,大则 1G+,以一般的HTTP请求发送数据的方式的话,会遇到的问题:

  • 1、文件过大,超出服务端的请求大小限制;
  • 2、请求时间过长,请求超时;
  • 3、传输中断,必须重新上传导致前功尽弃;

探索过程:

1、原先咨询过组里的大佬给我推荐了百度的webupload,但后来引入之后发现它是基于jquery封装的。由于本身项目是基于vue开发的所以与jquery相关的开源框架就尽量不考虑了。

2、后来查阅了资料后自己手动实现了文件切片上传到服务器基本需求已经实现,但由于效率及稳定性问题后来决定还是直传文件到七牛云。一开始我使用了表单上传的方式实现了,后来种种原因又要求我做成分片上传。

3、引入七牛的jssdk。

解决方案:

  • 1、修改服务端上传的限制配置;Nginx 以及 PHP 的上传文件限制 不宜过大,一般5M 左右为好;
  • 2、大文件分片,一片一片的传到服务端,再由服务端合并。这么做的好处在于一旦上传失败只是损失一个分片而已,不用整个文件重传,而且每个分片的大小可以控制在4MB以内,服务端限制在4M即可。
  • 3、使用七牛JavaScript SDK分片上传

首先,刚接触一门新的技术我们还是先去官方文档走一圈了解下基本用法~

文档地址:JavaScript SDK

Qiniu-JavaScript-SDK 为客户端 SDK,没有包含 token 生成实现,为了安全,token 建议通过网络从服务端获取,具体生成代码可以参考服务端 SDK 的文档。

功能简介

  • 上传

    • 大于 4M 时可分块上传,小于 4M 时直传
    • 分块上传时,支持断点续传
  • 数据处理(图片)
    • imageView2(缩略图)
    • imageMogr2(高级处理,包含缩放、裁剪、旋转等)
    • imageInfo (获取基本信息)
    • exif (获取图片 EXIF 信息)
    • watermark (文字、图片水印)
    • pipeline (管道,可对 imageView2、imageMogr2、watermark 进行链式处理)

后端返回给你的获取token的json格式必须是这种格式的。必须是一个json对象内部包裹着uptoken字段,带上其他字段也是可以的但是必须第一层要能找到uptoken

{
   "uptoken": "0MLvWPnyya1WtPnXFy9KLyGHyFPNdZceomL...",
   "xxx": "..."
}

因为在它的sdk源码中是这么获取token的。他会先找定义的option字段中是否有uptoken,如果没有再去找uptoken_url有就发送ajax请求去获取uptoken字段,倘若后端必须要以他的格式为主那你可以修改sdk源码来实现。如果uptoken_url也没有值就回去调用uptoken_func函数都没有则报错,所以这三个必须指定一个。

        // getUptoken maybe called at Init Event or BeforeUpload Event
       // case Init Event, the file param of getUptken will be set a null value
       // if op.uptoken has value, set uptoken with op.uptoken
       // else if op.uptoken_url has value, set uptoken from op.uptoken_url
       // else if op.uptoken_func has value, set uptoken by result of op.uptoken_func
       var getUpToken = function(file) {
           if (op.uptoken) {
               that.token = op.uptoken;
               return;
           } else if (op.uptoken_url) {
               logger.debug("get uptoken from: ", that.uptoken_url);
               // TODO: use mOxie
               var ajax = that.createAjax();
               ajax.open('GET', that.uptoken_url, false);
               ajax.setRequestHeader("If-Modified-Since", "0");
               // ajax.onreadystatechange = function() {
               //     if (ajax.readyState === 4 && ajax.status === 200) {
               //         var res = that.parseJSON(ajax.responseText);
               //         that.token = res.uptoken;
               //     }
               // };
               ajax.send();
               if (ajax.status === 200) {
                   var res = that.parseJSON(ajax.responseText);
                   that.token = res.uptoken;
                   logger.debug("get new uptoken: ", res.uptoken);
               } else {
                   logger.error("get uptoken error: ", ajax.responseText);
               }
               return;
           } else if (op.uptoken_func) {
               logger.debug("get uptoken from uptoken_func");
               that.token = op.uptoken_func(file);
               logger.debug("get new uptoken: ", that.token);
               return;
           } else {
               logger.error("one of [uptoken, uptoken_url, uptoken_func] settings in options is required!");
           }
       };

通过npm安装

npm install qiniu-js

在项目中使用import引入

import 'qiniu-js/dist/qiniu.min.js';

HTML

<div id="container">
    <div id="pickfiles">上传按钮</div>
</div>

JavaScript

 var uploader = Qiniu.uploader({
     runtimes: 'html5,flash,html4',      // 上传模式,依次退化(照着官网来就是了)
     browse_button: 'pickfiles',         // 上传选择的点选按钮,必需(记得定义id并且保持一致)
     // 在初始化时,uptoken,uptoken_url,uptoken_func三个参数中必须有一个被设置
     // 切如果提供了多个,其优先级为uptoken > uptoken_url > uptoken_func
     // 其中uptoken是直接提供上传凭证,uptoken_url是提供了获取上传凭证的地址,如果需要定制获取uptoken的过程则可以设置uptoken_func
     uptoken : '<Your upload token>', // uptoken是上传凭证,由其他程序生成
     uptoken_url: '/uptoken',         // Ajax请求uptoken的Url,强烈建议设置(服务端提供)
     uptoken_func: function(){        // 在需要获取uptoken时,该方法会被调用
        // do something(一般是发送手动发送ajax获取到token,如果后端返回格式不跟官方一致又不想该懂源代码可以通过这个方式调整)
        return uptoken;
     },
     get_new_uptoken: false,             // 设置上传文件的时候是否每次都重新获取新的uptoken(没有特殊需求一般为false)
     // downtoken_url: '/downtoken',(未使用到,可以不设置)
     // Ajax请求downToken的Url,私有空间时使用,JS-SDK将向该地址POST文件的key和domain,服务端返回的JSON必须包含url字段,url值为该文件的下载地址
     // unique_names: true,              // 默认false,key为文件名。若开启该选项,JS-SDK会为每个文件自动生成key(文件名)
     // save_key: true,                  // 默认false。若在服务端生成uptoken的上传策略中指定了sava_key,则开启,SDK在前端将不对key进行任何处理
     domain: '<Your bucket domain>',     // bucket域名,下载资源时用到,必需(找后端拿)
     container: 'container',             // 上传区域DOM ID,默认是browser_button的父元素(如果不实现拖拽上传可以不设置)
     max_file_size: '100mb',             // 最大文件体积限制(可以调大)
     flash_swf_url: 'path/of/plupload/Moxie.swf',  //引入flash,相对路径(如果没用到flash上传的话可以不设置,一般支持html5上传的浏览器都不会用到它)
     max_retries: 3,                     // 上传失败最大重试次数(自动帮你续传分片)
     dragdrop: true,                     // 开启可拖曳上传(如果不实现拖拽上传可以不设置)
     drop_element: 'container',          // 拖曳上传区域元素的ID,拖曳文件或文件夹后可触发上传(如果不实现拖拽上传可以不设置)
     chunk_size: '4mb',                  // 分块上传时,每块的体积
     auto_start: true,                   // 选择文件后自动上传,若关闭需要自己绑定事件触发上传
     //x_vars : {                        // (未使用到,可以不设置)
     //    查看自定义变量
     //    'time' : function(up,file) {
     //        var time = (new Date()).getTime();
               // do something with 'time'
     //        return time;
     //    },
     //    'size' : function(up,file) {
     //        var size = file.size;
               // do something with 'size'
     //        return size;
     //    }
     //},
     init: {
         'FilesAdded': function(up, files) {
             plupload.each(files, function(file) {
                 // 文件添加进队列后,处理相关的事情
             });
         },
         'BeforeUpload': function(up, file) {
                // 每个文件上传前,处理相关的事情
                // (上传文件前做一些处理)
         },
         'UploadProgress': function(up, file) {
                // 每个文件上传时,处理相关的事情
                // (可以设置进度条信息)
         },
         'FileUploaded': function(up, file, info) {
                // 每个文件上传成功后,处理相关的事情
                // 其中info是文件上传成功后,服务端返回的json,形式如:
                // {
                //    "hash": "Fh8xVqod2MQ1mocfI4S4KpRL6D98",
                //    "key": "gogopher.jpg"
                //  }
                // 查看简单反馈
                // var domain = up.getOption('domain');
                // var res = parseJSON(info);
                // var sourceLink = domain +"/"+ res.key; 获取上传成功后的文件的Url
         },
         'Error': function(up, err, errTip) {
                //上传出错时,处理相关的事情
         },
         'UploadComplete': function() {
                //队列文件处理完毕后,处理相关的事情
         },
         'Key': function(up, file) {
             // 若想在前端对每个文件的key进行个性化处理,可以配置该函数
             // 该配置必须要在unique_names: false,save_key: false时才生效

             var key = "";
             // do something with key here
             // (可以自定义key不设定默认是文件名)
             return key
         }
     }
 });

 // domain为七牛空间对应的域名,选择某个空间后,可通过 空间设置->基本设置->域名设置 查看获取

 // uploader为一个plupload对象,继承了所有plupload的方法

总结

由于本次项目中只涉及到大文件上传,没有图像处理等相关的api使用经验官方的案例就不多讲了。总结起来七牛云上传的套路就是后台为你提供uptoken或者获取uptoken的接口地址之后上传的时候要带上这个token。返回的字段最好是按照官方的格式来,如果不是的话也可以修改源代码或者在uptoken_func中手动获取,另外如果要修改上传的服务器也是要在qiniu.js中修改

    /**
    * qiniu upload urls
    * 'qiniuUploadUrls' is used to change target when current url is not avaliable
    * @type {Array}
    */
   var qiniuUploadUrls = [
       // "http://upload.qiniu.com",
       // "http://up.qiniu.com",
       "修改成你需要的地址",
   ];

如果使用表单上传的话可以不引用任何插件,代码实现如下:

    <form id="testform" method="post" enctype="multipart/form-data">
            <input name="key" id="key" type="hidden" value="">
            <input name="token" type="hidden" id="token" value="">
            <input id="userfile" name="file" type="file" />

            <!-- take photo with phone -->
            <!-- <input id="userfile" name="file" accept="image/*" type="file" /> -->

            <!-- take video with phone -->
            <!-- <input id="userfile" name="file" type="file" accept="video/*"/> -->

            <input name="accept" type="hidden" />
        </form>

JS:

    upload() {
        const formdata = new FormData(document.getElementById('testform'));
        $.ajax({
            url: '上传的七牛云服务器,后端提供', // 'http://up.qiniu.com'
            method: 'post',
            success: function(data) {
                console.log(data);
            },
        })
        ...
    }

需要注意的是,每个input都需要定义好那么属性,并且token不能为空,需要提前通过ajax去后端获取或者使用后端给定的token否则上传会失败~

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • js自己实现一个大文件切片上传+断点续传的示例代码

    目录 首先我们来分析一下需求 一. 格式校验 二. 文件切片 三. 断点续传 + 秒传 + 上传进度 PM:喂,那个切图仔,我这里有个100G的视频要上传,你帮我做一个上传后台,下班前给我哦,辛苦了.我:...相信每个切图工程师,都接触过文件上传的需求,一般的小文件,我们直接使用 input file,然后构造一个 new FormData()对象,扔给后端就可以了.如果使用了 Ant design 或者 element ui 之类的ui库,那更简单,直接调用一下api即可.当然了,复杂一些的,

  • 如何基于js管理大文件上传及断点续传详析

    目录 前言 前端结构 后端结构(node + express) 基于FormData实现文件上传 基于BASE64实现文件上传 BASE64具体方法 前端生成文件名传给后端 上传进度管控 大文件上传 服务端代码(大文件上传+断点续传) 总结 前言 前端小伙伴们平常在开发过程中文件上传是经常遇到的一个问题,也许你能够实现相关的功能,但是做完后回想代码实现上是不是有点"力不从心"呢?你真的了解文件上传吗?如何做到大文件上传以及断电续传呢,前后端通讯常用的格式,文件上传进度管控,服务端是如何

  • Vue+NodeJS实现大文件上传的示例代码

    目录 整体思路 项目演示 前端界面 文件切片 hash计算 查询切片状态 切片上传(断点续传) 文件总体上传进度 合并文件 优化 请求并发数控制 hash值计算优化 常见的文件上传方式可能就是new一个FormData,把文件append进去以后post给后端就可以了.但如果采用这种方式来上传大文件就很容易产生上传超时的问题,而且一旦失败还得从新开始,在漫长的等待过程中用户还不能刷新浏览器,不然前功尽弃.因此这类问题一般都是通过切片上传. 整体思路 将文件切成多个小文件 hash计算,需要计算一

  • Vue+Node实现大文件上传和断点续传

    目录 源代码 Blob.slice 切片 初始化文件内容 FormData.append() 大文件上传 断点续传 代码 创建切片 源码 worker 线程通讯的逻辑 断点续传 秒传 源代码 断点续传.分片上传.秒传.重试机制 文件上传是开发中的难点, 大文件上传及断点续传 难点中的细节及核心技术点. element-ui 框架的上传组件,是默认基于文件流的. 数据格式:form-data: 传递的数据: file 文件流信息:filename 文件名字 通过 fileRead.readAsDa

  • Vue 大文件上传和断点续传的实现

    文件上传的 2 套方案 基于文件流(form-data) element-ui 框架的上传组件,就是默认基于文件流的. 数据格式:form-data: 传递的数据: file 文件流信息:filename 文件名字 客户端把文件转换为 base64 通过 fileRead.readAsDataURL(file) 转为 base64 字符串后,要用 encodeURIComponent 编译再发送, 发送的数据经由 qs.stringify 处理,请求头添加 "Content-Type"

  • JavaScript实现大文件分片上传处理

    很多时候我们在处理文件上传时,如视频文件,小则几十M,大则 1G+,以一般的HTTP请求发送数据的方式的话,会遇到的问题: 1.文件过大,超出服务端的请求大小限制: 2.请求时间过长,请求超时: 3.传输中断,必须重新上传导致前功尽弃 这些问题很影响用户的体验感,所以下面介绍一种基于原生JavaScript进行文件分片处理上传的方案,具体实现过程如下: 1.通过dom获取文件对象,并且对文件进行MD5加密(文件内容+文件标题形式),采用SparkMD5进行文件加密: 2.进行分片设置,文件Fil

  • vue实现大文件分片上传与断点续传到七牛云

    问题: 前段时间做视频上传业务,通过网页上传视频到服务器. 视频大小 小则几十M,大则 1G+,以一般的HTTP请求发送数据的方式的话,会遇到的问题: 1.文件过大,超出服务端的请求大小限制: 2.请求时间过长,请求超时: 3.传输中断,必须重新上传导致前功尽弃: 探索过程: 1.原先咨询过组里的大佬给我推荐了百度的webupload,但后来引入之后发现它是基于jquery封装的.由于本身项目是基于vue开发的所以与jquery相关的开源框架就尽量不考虑了. 2.后来查阅了资料后自己手动实现了文

  • React+Node实现大文件分片上传、断点续传秒传思路

    目录 1.整体思路 2.实现步骤 2.1 文件切片加密 2.2 查询上传文件状态 2.3 秒传 2.4 上传分片.断点续传 2.5 合成分片还原完整文件 3.总结 4.后续扩展与思考 5.源码 1.整体思路 将文件切成多个小的文件: 将切片并行上传: 所有切片上传完成后,服务器端进行切片合成: 当分片上传失败,可以在重新上传时进行判断,只上传上次失败的部分实现断点续传: 当切片合成为完整的文件,通知客户端上传成功: 已经传到服务器的完整文件,则不需要重新上传到服务器,实现秒传功能: 2.实现步骤

  • vue 大文件分片上传(断点续传、并发上传、秒传)

    对于大文件的处理,无论是用户端还是服务端,如果一次性进行读取发送.接收都是不可取,很容易导致内存问题.所以对于大文件上传,采用切块分段上传,从上传的效率来看,利用多线程并发上传能够达到最大效率. 本文是基于 springboot + vue 实现的文件上传,本文主要介绍vue实现文件上传的步骤及代码实现,服务端(springboot)的实现步骤及实现请移步本人的另一篇文章: springboot 大文件上传.分片上传.断点续传.秒传 上传分步: 本人分析上传总共分为: MD5读取文件,获取文件的

  • Java超详细大文件分片上传代码

    目录 Java 大文件分片上传 首先是交互的控制器 上传文件分片参数接收 大文件分片上传服务类实现 文件分片上传定义公共服务类接口 文件分片上传文件操作接口实现类 OSS阿里云对象存储分片上传实现 京东云对象存储实现 腾讯云对象存储分片上传 分片上传前端代码实现 Java 大文件分片上传 原理:前端通过js读取文件,并将大文件按照指定大小拆分成多个分片,并且计算每个分片的MD5值.前端将每个分片分别上传到后端,后端在接收到文件之后验证当前分片的MD5值是否与上传的MD5一致,待所有分片上传完成之

  • 前端使用koa实现大文件分片上传

    目录 引言 前端 拆分上传的文件流 后端 接收文件片段 合并文件片段 总结 引言 一个文件资源服务器,很多时候需要保存的不只是图片,文本之类的体积相对较小的文件,有时候,也会需要保存音视频之类的大文件.在上传这些大文件的时候,我们不可能一次性将这些文件数据全部发送,网络带宽很多时候不允许我们这么做,而且这样也极度浪费网络资源. 因此,对于这些大文件的上传,往往会考虑用到分片传输. 分片传输,顾名思义,也就是将文件拆分成若干个文件片段,然后一个片段一个片段的上传,服务器也一个片段一个片段的接收,最

  • webuploader在springMVC+jquery+Java开发环境下的大文件分片上传的实例代码

    注意: 1,webuploader上传组件会和jQuery自带的上传组件冲突,所以不要使用<form>标签中添加上传文件的属性; enctype="multipart/form-data" 2.并且屏蔽ApplicationContext-mvc.xml里面的拦截配置! <!-- 上传拦截,如最大上传值及最小上传值 --> <!--新增加的webuploader上传组件,必须要屏蔽这里的拦截机制 <bean id="multipartRes

  • PHP大文件分片上传的实现方法

    一.前言 在网站开发中,经常会有上传文件的需求,有的文件size太大直接上传,经常会导致上传过程中耗时太久,大量占用带宽资源,因此有了分片上传. 分片上传主要是前端将一个较大的文件分成等分的几片,标识当前分片是第几片和总共几片,待所有的分片均上传成功的时候,在后台进行合成文件即可. 二.开发过程中遇到的问题 分片的时候每片该分多大size?太大会出现"413 request entity too large" 分片上传的时候并不是严格按照分片的序号顺序上传,如何判断所有的分片均上传成功

  • .NET Core Web APi大文件分片上传研究实现

    前言 前两天发表利用FormData进行文件上传,然后有人问要是大文件几个G上传怎么搞,常见的不就是分片再搞下断点续传,动动手差不多也能搞出来,只不过要深入的话,考虑的东西还是很多.由于断点续传之前写个几篇,这里试试利用FormData来进行分片上传. .NET Core Web APi文件分片上传 这里我们依然是使用FormData来上传,只不过在上传之前对文件进行分片处理,如下HTML代码 <div class="form-horizontal" style="ma

  • Java实现浏览器端大文件分片上传

    目录 背景介绍 项目介绍 需要知识点 启动项目 项目示范 核心讲解 核心原理 功能分析 分块上传 秒传功能 断点续传 总结 参考文献 背景介绍   Breakpoint-http,是不是觉得这个名字有点low,break point断点.这是一个大文件上传的一种实现.因为本来很久没写过前端了,本来想自己好好写一番js,可惜因为种种原因而作罢了.该项目是基于一款百度开源的前端上传控件:WebUploader(百度开源的东西文档一如既往的差,哈哈.或者是我理解能力差).   Breakpoint-h

随机推荐