问题:

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

视频大小 小则几十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 的文档。

  • JavaScript SDK 下载地址
  • JavaScript SDK 源码地址
  • JavaScript 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否则上传会失败~

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

vue实现大文件分片上传与断点续传到七牛云的更多相关文章

  1. Vue如何指定不编译的文件夹和favicon.ico

    这篇文章主要介绍了Vue如何指定不编译的文件夹和favicon.ico,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

  2. AngularJs上传前预览图片的实例代码

    使用AngularJs进行开发,在项目中,经常会遇到上传图片后,需在一旁预览图片内容,怎么实现这样的功能呢?今天小编给大家分享AugularJs上传前预览图片的实现代码,需要的朋友参考下吧

  3. iOS:调试无法在XCode中运行

    我正在使用XCode4和iOSSDK4.3.我的调试工作正常,但现在我发现在设置断点时,应用暂停,但XCode不关注编辑器中的行.点击断点时也不会显示绿色箭头.我有一个在AppDelegate中分配的UINavigationController.当我在didFinishLaunchingWithOptions中设置断点时,一切都按预期工作:这是当一个断点暂停了mapViewController中的

  4. ios – 异常断点处于活动状态时,应用程序在启动时崩溃

    我刚开始继续开发一款适用于商店的传统iPad应用程序.我注意到项目中的异常断点未启用.当我启用它时,应用程序在启动时崩溃,但在输出窗口中没有给出任何信息,而在线程视图中只有相当无用的信息(见下文)我试着解决它..>将Autolayout设置为关闭.>通过编辑和重新保存故事板文件..但到目前为止没有运气.我的猜测是,故事板中的某些内容被破坏了,因为AppDelegates“确实完成了启动……”

  5. xcode – 如何通过LLDB命令行添加断点操作?

    如果你从Xcode编辑一个断点,有一个超级有用的选项,可以添加一个“Action”,以便在每次遇到断点时自动执行.如何从LLDB命令行添加此类操作?

  6. xcode – 如何在LLDB断点条件下使用堆栈内容?

    问题:我有一种情况,我们在发布期间有媒体播放,并且objc_exception_throw()在此期间大约有5次点击,但总是被捕获,并且它在媒体播放器对象的南边.我厌倦了(a)必须手动连续n次,或者(b)在播放完成之前必须禁用断点.我尝试过的:>使断点忽略前五次命中(问题:它并不总是正好五次)>使用我的目标作为模块创建我自己的符号断点(问题:没有改变)我想做什么:想到的一个解决方案是在断点命中时评

  7. Xcode 4.3.1:在以下情况下不显示代码行:由于未捕获的异常而终止应用程序

    在Xcode的早期版本中,当我遇到崩溃时,Xcode通常会打开发生崩溃的文件,并经常将我带到崩溃的行.最新的Xcode似乎没有做那些让调试变得更难的东西.我是否需要启用一些新设置?

  8. ios – XCode断点应该只挂起当前线程

    我需要调试多线程错误.因此,为了获得生成崩溃的条件,我需要在代码中的特定点停止一个线程,并等待另一个线程到达第二个断点.我现在遇到的问题是,如果一个线程遇到断点,则所有其他线程都被挂起.有没有办法只停止一个线程,让其他线程运行,直到它们到达第二个断点?)其他更有趣的选择:当你点击第一个断点时,你可以进入控制台并写入这应该在该断点处暂停当前上下文中的线程一小时.然后在Xcode中恢复执行.

  9. 在Xcode中的选择器上添加符号断点

    我的应用程序中有一个错误,显示以下(部分)堆栈跟踪:为了调试这个,我决定在–[EventboolValue]上添加一个符号断点,推断当发送该选择器时,调试器将停止.然而,没有任何反应.设置断点后,应用程序只是士兵并生成相同的异常而不停止.我已经定义了断点如下:我正在使用LLDB调试器和Xcode4.2解决方法在选择器上设置断点会导致lldb在执行该选择器时停止,而不是在发送时停止.在你的情况下,没

  10. ios – 如何在Xcode 6中的异常断点上打印异常?

    我的应用程序正在崩溃,它似乎陷入了异常断点(这是有道理的),但我无法找到崩溃的原因.这是我尝试过的:>po$eax>po$rax>po$r0>po*(id*)($esp4)对于上述所有尝试,我收到以下错误:错误:使用未声明的标识符’$‘错误:解析表达式时出错1次我也找到了这个LLDBCommandGuide,但没有找到任何有用的东西(有点令人困惑,你不知道你在寻找什么)

随机推荐

  1. js中‘!.’是什么意思

  2. Vue如何指定不编译的文件夹和favicon.ico

    这篇文章主要介绍了Vue如何指定不编译的文件夹和favicon.ico,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

  3. 基于JavaScript编写一个图片转PDF转换器

    本文为大家介绍了一个简单的 JavaScript 项目,可以将图片转换为 PDF 文件。你可以从本地选择任何一张图片,只需点击一下即可将其转换为 PDF 文件,感兴趣的可以动手尝试一下

  4. jquery点赞功能实现代码 点个赞吧!

    点赞功能很多地方都会出现,如何实现爱心点赞功能,这篇文章主要为大家详细介绍了jquery点赞功能实现代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  5. AngularJs上传前预览图片的实例代码

    使用AngularJs进行开发,在项目中,经常会遇到上传图片后,需在一旁预览图片内容,怎么实现这样的功能呢?今天小编给大家分享AugularJs上传前预览图片的实现代码,需要的朋友参考下吧

  6. JavaScript面向对象编程入门教程

    这篇文章主要介绍了JavaScript面向对象编程的相关概念,例如类、对象、属性、方法等面向对象的术语,并以实例讲解各种术语的使用,非常好的一篇面向对象入门教程,其它语言也可以参考哦

  7. jQuery中的通配符选择器使用总结

    通配符在控制input标签时相当好用,这里简单进行了jQuery中的通配符选择器使用总结,需要的朋友可以参考下

  8. javascript 动态调整图片尺寸实现代码

    在自己的网站上更新文章时一个比较常见的问题是:文章插图太宽,使整个网页都变形了。如果对每个插图都先进行缩放再插入的话,太麻烦了。

  9. jquery ajaxfileupload异步上传插件

    这篇文章主要为大家详细介绍了jquery ajaxfileupload异步上传插件,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  10. React学习之受控组件与数据共享实例分析

    这篇文章主要介绍了React学习之受控组件与数据共享,结合实例形式分析了React受控组件与组件间数据共享相关原理与使用技巧,需要的朋友可以参考下

返回
顶部