• 使用resumable.js上传大文件(视频)兵转换flv格式


    前台代码

      1 <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Video.aspx.cs" Inherits="BPMS.WEB.Video" %>
      2 
      3 <!DOCTYPE html>
      4 
      5 <html xmlns="http://www.w3.org/1999/xhtml">
      6 <head runat="server">
      7     <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
      8     <meta name="renderer" content="webkit" />
      9     <meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1" />
     10     <title></title>
     11     <script src="/Themes/Scripts/jquery-1.8.2.min.js"></script>
     12     <link rel="stylesheet" type="text/css" href="/ddUpload/css/style.css" />
     13     <script src="/ddUpload/js/resumable.js" charset="utf-8"></script>
     14 </head>
     15 <body>
     16     
     17      <div id="frame">
     18             &nbsp;<br />
     19             <span style="color: red; font-size: 12px;" id="spanerr"></span>
     20             <div class="resumable-drop" ondragenter="jQuery(this).addClass('resumable-dragover');" ondragend="jQuery(this).removeClass('resumable-dragover');" ondrop="jQuery(this).removeClass('resumable-dragover');">
     21                 <a class="resumable-browse" href="#" style="text-decoration: none;">选择视频</a>
     22             </div>
     23             <div class="resumable-progress">
     24                 <table>
     25                     <tr>
     26                         <td width="100%">
     27                             <div class="progress-container">
     28                                 <div class="progress-bar"></div>
     29                             </div>
     30                         </td>
     31                         <td class="progress-text" nowrap="nowrap"></td>
     32                         <td class="progress-pause" nowrap="nowrap">
     33                             <a href="#" onclick="r.upload(); return(false);" class="progress-resume-link">
     34                                 <img src="/ddUpload/css/resume.png" title="Resume upload" /></a>
     35                             <a href="#" onclick="r.pause(); return(false);" class="progress-pause-link">
     36                                 <img src="/ddUpload/css/pause.png" title="Pause upload" /></a>
     37                         </td>
     38                     </tr>
     39                 </table>
     40             </div>
     41             <ul class="resumable-list"></ul>
     42             <script>
     43                 var r = new Resumable({
     44                     target: '/ddUpload/savefile.aspx',
     45                     chunkSize: 1 * 1024 * 1024,
     46                     simultaneousUploads: 1,
     47                     testChunks: false,
     48                     throttleProgressCallbacks: 1,
     49                     method: "octet"
     50                 });
     51                 // Resumable.js isn't supported, fall back on a different method
     52                 if (!r.support) {
     53                     $('.resumable-error').show();
     54 
     55                 } else {
     56                     // Show a place for dropping/selecting files
     57                     $('.resumable-drop').show();
     58                     r.assignDrop($('.resumable-drop')[0]);
     59                     r.assignBrowse($('.resumable-browse')[0]);
     60                     var objName = "";
     61                     // Handle file add event
     62                     r.on('fileAdded', function (file) {
     63                         file.startchunkindex = 0; // 设置当前文件开始上传的块数
     64                         // Show progress pabr
     65                         $('.resumable-progress, .resumable-list').show();
     66                         // Show pause, hide resume
     67                         $('.resumable-progress .progress-resume-link').hide();
     68                         $('.resumable-progress .progress-pause-link').show();
     69                         // Add the file to the list
     70                         $('.resumable-list').append('<li class="resumable-file-' + file.uniqueIdentifier + '">Uploading <span class="resumable-file-name"></span> <span class="resumable-file-progress"></span>');
     71                         $('.resumable-file-' + file.uniqueIdentifier + ' .resumable-file-name').html(file.fileName);
     72                         objName = file.fileName;
     73                         // Actually start the upload
     74                         r.upload();
     75                     });
     76 
     77                     r.on('uploadStart', function () {
     78                         $('.resumable-progress .progress-resume-link').hide();
     79                         $('.resumable-progress .progress-pause-link').show();
     80                     });
     81                     r.on('pause', function () {
     82                         // Show resume, hide pause
     83                         $('.resumable-progress .progress-resume-link').show();
     84                         $('.resumable-progress .progress-pause-link').hide();
     85                     });
     86                     r.on('complete', function () {
     87                         // Hide pause/resume when the upload has completed
     88                         $('.resumable-progress .progress-resume-link, .resumable-progress .progress-pause-link').hide();
     89                         $("#spanjindu").html("文件上传完成正在转码!请耐心等候!");
     90                         $.ajax({
     91                             //请求的路径
     92                             url: "/CommonModule/TB_Video/UploadHandler.ashx?action=VideoConvert&FilePath=" + objName,
     93                             //请求的方法
     94                             type: "post",
     95                             dataType: "json",
     96                             //请求成功时调用
     97                             success: function (msg) {
     98                                 if (msg["msg"] != "0") {
     99                                     $("#spanjindu").html("转码完成!请保存数据!");
    100                                     window.location = "/Video.aspx";
    101                                 } else {
    102                                     $("#spanjindu").html("转码失败!请联系相关人员");
    103                                 }
    104                             },
    105                             //请求失败时调用
    106                             error: function (msg) {
    107                                 alert(msg);
    108                             }
    109                         });
    110 
    111 
    112                     });
    113                     r.on('fileSuccess', function (file, message) {
    114                         // Reflect that the file upload has completed
    115                         $('.resumable-file-' + file.uniqueIdentifier + ' .resumable-file-progress').html('(completed)');
    116                     });
    117                     r.on('fileError', function (file, message) {
    118                         // Reflect that the file upload has resulted in error
    119                         $('.resumable-file-' + file.uniqueIdentifier + ' .resumable-file-progress').html('(file could not be uploaded: ' + message + ')');
    120                     });
    121                     r.on('fileProgress', function (file) {
    122                         //alert(file.progress());
    123                         // Handle progress for both the file and the overall upload
    124 
    125                         $('.resumable-file-' + file.uniqueIdentifier + ' .resumable-file-progress').html(Math.floor(file.progress() * 100) + '%');
    126                         $('.progress-bar').css({  Math.floor(r.progress() * 100) + '%' });
    127                     });
    128                 }
    129             </script>
    130         </div>
    131         <div style="padding-top: 50px; padding-left: 200px;">
    132             <span style="color: blue; font-size: 16px" id="spanjindu"></span>
    133             <br />
    134             视频列表:<br />
    135             <ul>
    136                 <asp:Literal ID="Literal1" runat="server"></asp:Literal>
    137             </ul>
    138         </div>
    139 
    140 </body>
    141 </html>
    View Code

    后台.cs

     1 using System;
     2 using System.Collections.Generic;
     3 using System.Data;
     4 using System.Linq;
     5 using System.Text;
     6 using System.Web;
     7 using System.Web.UI;
     8 using System.Web.UI.WebControls;
     9 
    10 namespace BPMS.WEB
    11 {
    12     public partial class Video : System.Web.UI.Page
    13     {
    14         protected void Page_Load(object sender, EventArgs e)
    15         {
    16             load(); 
    17         }
    18         public void load() 
    19         {
    20             int TotalRecord = 0; int TotalPage = 0;
    21             DataTable dt = new BPMS.Business.GetPageTab().GetTab("SELECT *  FROM TB_Video" , 1, 100, "ID", "ID", out TotalRecord, out TotalPage);
    22              StringBuilder sb = new StringBuilder();
    23             foreach (DataRow row in dt.Rows)
    24             {
    25                sb.Append("<li style="padding:4px 7px 2px 4px"><a target="_blank" href="/play/WebForm1.aspx?path=" +  HttpUtility.UrlEncode((row["FilePath"].ToString())) + "">" + row["FilePath"] + "   观看</a></li>");
    26             }
    27             this.Literal1.Text = sb.ToString();
    28         }
    29     }
    30 }
    View Code

    上传代码

     1 using System;
     2 using System.Collections.Generic;
     3 using System.IO;
     4 using System.Linq;
     5 using System.Web;
     6 using System.Web.UI;
     7 using System.Web.UI.WebControls;
     8 
     9 namespace Html5Upload
    10 {
    11     public partial class savefile : System.Web.UI.Page
    12     {
    13         protected void Page_Load(object sender, EventArgs e)
    14         {
    15             System.Threading.Thread.Sleep(1000);
    16             Response.AddHeader("Content-Type", "application/json");
    17 
    18             if (Request.QueryString["resumableChunkNumber"] != null)
    19             {
    20                 string filedir = Request.MapPath("/ddUpload/temp/");
    21                 string savefile =  filedir+ Request.QueryString["resumableChunkNumber"] + ".lzp";
    22                 //Request.Files[0].SaveAs(savefile);
    23                 byte[] data = Request.BinaryRead(Request.ContentLength);
    24                 using (Stream file = File.Create(savefile))
    25                 {
    26                     file.Write(data, 0, data.Length);
    27                     file.Close();
    28                 }
    29 
    30                 if (Request.QueryString["resumableChunkNumber"] == Request.QueryString["resumableTotalChunks"])
    31                 {
    32                     MergeFile(filedir, ".lzp", Request.QueryString["resumableFilename"]);
    33                 }
    34             }
    35             
    36             Response.Write("die('{"jsonrpc" : "2.0", "result" : null, "id" : "id"}');");
    37             
    38         }
    39 
    40         /// <summary>
    41         /// 要合并的文件夹目录
    42         /// </summary>
    43         /// <param name="filePath">文件目录</param>
    44         /// <param name="Extension">扩展名</param>
    45         /// <param name="filename">合并文件名</param>
    46         bool MergeFile(string filePath, string Extension,string filename)
    47         {
    48             bool rBool = false;
    49             //获得当前目录下文件夹列表,按文件名排序
    50             SortedList<int, string> FileList = new SortedList<int, string>();
    51             DirectoryInfo dirInfo = new DirectoryInfo(filePath);
    52 
    53             foreach (FileSystemInfo var in dirInfo.GetFileSystemInfos())
    54             {
    55                 if (var.Attributes != FileAttributes.Directory)
    56                 {
    57                     if (var.Extension == Extension)
    58                     {
    59                         FileList.Add(Convert.ToInt32(var.Name.Replace(Extension, "")), var.Name);
    60                     }
    61                 }
    62             }
    63 
    64             if (FileList.Count > 0) //存在文件
    65             {
    66                 FileStream outFile = new FileStream(filePath + "\" + filename, FileMode.OpenOrCreate, FileAccess.Write);
    67                 using (outFile)
    68                 {
    69                     foreach (int item in FileList.Keys)
    70                     {
    71                         int data = 0;
    72                         byte[] buffer = new byte[1024];
    73 
    74                         FileStream inFile = new FileStream(filePath + "\" + FileList[item], FileMode.OpenOrCreate, FileAccess.Read);
    75                         using (inFile)
    76                         {
    77                             while ((data = inFile.Read(buffer, 0, 1024)) > 0)
    78                             {
    79                                 outFile.Write(buffer, 0, data);
    80                             }
    81                             inFile.Close();
    82                         }
    83                     }
    84                     outFile.Close();
    85                     rBool = true; //合并成功
    86                 }
    87             }
    88 
    89             return rBool;
    90         }
    91     }
    92 }
    View Code

    视频转码代码

      1 using DotNet.Utilities;
      2 using System;
      3 using System.Collections.Generic;
      4 using System.IO;
      5 using System.Linq;
      6 using System.Web;
      7 
      8 namespace BPMS.WEB.CommonModule.TB_Video
      9 {
     10     /// <summary>
     11     /// UploadHandler 的摘要说明
     12     /// </summary>
     13     public class UploadHandler : IHttpHandler
     14     {
     15 
     16         public void ProcessRequest(HttpContext context)
     17         {
     18             context.Response.ContentType = "text/plain";
     19             context.Response.Buffer = true;
     20             context.Response.ExpiresAbsolute = DateTime.Now.AddDays(-1);
     21             context.Response.AddHeader("pragma", "no-cache");
     22             context.Response.AddHeader("cache-control", "");
     23             context.Response.CacheControl = "no-cache";
     24             string active = HttpContext.Current.Request["action"];
     25             
     26             switch (active)
     27             {
     28                 //case "Uploadify": //上传文件
     29                 //    HttpPostedFile file = context.Request.Files["Filedata"];
     30                 //    string uploadPath = HttpContext.Current.Server.MapPath(@context.Request["folder"]) + "\";
     31                 //    if (file != null)
     32                 //    {
     33                 //        string _FileName = file.FileName;
     34                 //        string _FileSize = FileHelper.CountSize(file.ContentLength);
     35                 //        string _Extension = System.IO.Path.GetExtension(file.FileName).ToLower();
     36                         
     37                 //        if (!Directory.Exists(uploadPath))
     38                 //        {
     39                 //            Directory.CreateDirectory(uploadPath);
     40                 //        }
     41                 //        //+ _Extension
     42                 //        file.SaveAs(uploadPath + _FileName );
     43                 //        context.Response.Write("1");
     44                 // }
     45                 //    else
     46                 //    {
     47                 //        context.Response.Write("0");
     48                 //    }
     49                 //    break;
     50                 //case "Delete"://删除文件
     51                 //    break;
     52                 //case "download"://下载
     53                     
     54                 //    break;
     55                 case "VideoConvert":
     56                     VideoConvert(context);
     57                     break;
     58                 default:
     59                     break;
     60             }
     61         }
     62 
     63         public void VideoConvert(HttpContext context) 
     64         {
     65             string FilePath = context.Request["FilePath"];
     66             string path1 = "/ddUpload/temp/" + FilePath;
     67             string path2Name = FilePath.Substring(0,FilePath.LastIndexOf('.'))+DateTime.Now.ToString("yyyyMMddHHmmss");
     68             string path2 = "/shuchu/"+path2Name+".flv";
     69             BPMS.WEB.Common.VideoConvert con = new Common.VideoConvert();
     70 
     71             bool isok = false;
     72             string houzhui = FilePath.Substring(FilePath.LastIndexOf('.'));
     73             if (houzhui.ToLower() == ".flv")
     74             {
     75                 File.Copy(context.Server.MapPath(path1),context.Server.MapPath(path2));
     76                 isok = true;
     77             }
     78             else 
     79             {
     80                 isok = con.ConvertFlv(path1, path2);
     81             }
     82 
     83             if (isok)
     84             {
     85                 BPMS.Business.TB_Video bll = new Business.TB_Video();
     86                 BPMS.Entity.TB_Video entity = new BPMS.Entity.TB_Video();
     87                 entity.FilePath = path2Name;
     88                 //entity.UserID = RequestSession.GetSessionUser().UserId;
     89                 //entity.UserName = RequestSession.GetSessionUser().UserName;
     90                 bll.Add(entity) ;
     91                 context.Response.Write("{"msg":""+path2Name+""}");
     92                 DeleteSignedFile(context.Server.MapPath("/ddUpload/temp/"), "lzp");
     93             }
     94             else 
     95             {
     96                 context.Response.Write("{"msg":"0"}");
     97             }
     98             context.Response.End();
     99 
    100         }
    101 
    102         /// <summary>
    103         /// 删除给定路径下的给定后缀名的文件
    104         /// </summary>
    105         /// <param name="path">传入路径</param>
    106         /// <param name="suffixName">传入后缀名</param>
    107         /// <returns>删除文件列表</returns>
    108         private static string[] DeleteSignedFile(string path, string suffixName)
    109         {
    110             string deletefiles = "";  //记录删除的文件名称
    111 
    112             DirectoryInfo di = new DirectoryInfo(path);
    113             //遍历该路径下的所有文件
    114             foreach (FileInfo fi in di.GetFiles())
    115             {
    116                 string exname = fi.Name.Substring(fi.Name.LastIndexOf(".") + 1);//得到后缀名
    117                 //判断当前文件后缀名是否与给定后缀名一样
    118                 if (exname == suffixName)
    119                 {
    120                     File.Delete(path + "\" + fi.Name);//删除当前文件
    121                     deletefiles += fi.Name + ",";//追加删除文件列表
    122                 }
    123             }
    124 
    125             if (deletefiles != "")
    126                 deletefiles = deletefiles.Substring(0, deletefiles.Length - 1);
    127             return deletefiles.Split(',');//以数组形式返回删除文件列表
    128 
    129         }
    130 
    131         public bool IsReusable
    132         {
    133             get
    134             {
    135                 return false;
    136             }
    137         }
    138     }
    139 }
    View Code

     引用js代码

      1 /*
      2  * MIT Licensed
      3  * http://www.23developer.com/opensource
      4  * http://github.com/23/resumable.js
      5  * Steffen Tiedemann Christensen, steffen@23company.com
      6  */
      7 
      8 (function () {
      9     "use strict";
     10 
     11     var Resumable = function (opts) {
     12         if (!(this instanceof Resumable)) {
     13             return new Resumable(opts);
     14         }
     15         this.version = 1.0;
     16         // SUPPORTED BY BROWSER?
     17         // Check if these features are support by the browser:
     18         // - File object type
     19         // - Blob object type
     20         // - FileList object type
     21         // - slicing files
     22         this.support = (
     23           (typeof (File) !== 'undefined') &&
     24           (typeof (Blob) !== 'undefined') &&
     25           (typeof (FileList) !== 'undefined') &&
     26           (!!Blob.prototype.webkitSlice || !!Blob.prototype.mozSlice || !!Blob.prototype.slice || false)
     27         );
     28         if (!this.support) {
     29             //alert("此上传控件兼容 火狐firefox, 谷歌Google Chrome,IE10 以上等浏览器!你的浏览器不支持此上传!");
     30             document.getElementById('spanerr').innerHTML = "提示:此上传控件兼容 火狐firefox, 谷歌Google Chrome,IE10 以上等浏览器!如果是双核模式浏览器,如360,百度,搜狗等浏览器!可切换成谷歌内核(极速模式)!<img src='/ddUpload/css/err.png'/>";
     31             return (false);
     32         }
     33 
     34 
     35         // PROPERTIES
     36         var $ = this;
     37         $.files = [];
     38         $.defaults = {
     39             chunkSize: 1 * 1024 * 1024,
     40             forceChunkSize: false,
     41             simultaneousUploads: 3,
     42             fileParameterName: 'file',
     43             throttleProgressCallbacks: 0.5,
     44             query: {},
     45             headers: {},
     46             preprocess: null,
     47             method: 'multipart',
     48             prioritizeFirstAndLastChunk: false,
     49             target: '/',
     50             testChunks: true,
     51             generateUniqueIdentifier: null,
     52             maxChunkRetries: undefined,
     53             chunkRetryInterval: undefined,
     54             permanentErrors: [404, 415, 500, 501],
     55             maxFiles:1,//undefined,
     56             withCredentials: false,
     57             xhrTimeout: 0,
     58             maxFilesErrorCallback: function (files, errorCount) {
     59                 var maxFiles = $.getOpt('maxFiles');
     60                 alert('Please upload ' + maxFiles + ' file' + (maxFiles === 1 ? '' : 's') + ' at a time.');
     61             },
     62             minFileSize: 1,
     63             minFileSizeErrorCallback: function (file, errorCount) {
     64                 alert(file.fileName || file.name + ' is too small, please upload files larger than ' + $h.formatSize($.getOpt('minFileSize')) + '.');
     65             },
     66             maxFileSize: undefined,
     67             maxFileSizeErrorCallback: function (file, errorCount) {
     68                 alert(file.fileName || file.name + ' is too large, please upload files less than ' + $h.formatSize($.getOpt('maxFileSize')) + '.');
     69             },
     70             fileType: ['mp4', 'flv', 'rm', 'rmvb', 'avi', 'wmv', 'mpg', 'mpeg', '3gp', 'swf', 'asf', 'divx', 'xvid', '3gp2', 'flv1', 'mpeg1', 'mpeg2', 'mpeg3', 'mpeg4', 'h264'],
     71             fileTypeErrorCallback: function (file, errorCount) {
     72                 //alert(file.fileName || file.name + '' + $.getOpt('fileType') + '.');
     73                 document.getElementById('spanjindu').innerHTML = "请上传视频文件!";
     74                 //$("#spanjindu").html("请上传视频文件!");
     75             }
     76         };
     77         $.opts = opts || {};
     78         $.getOpt = function (o) {
     79             var $opt = this;
     80             // Get multiple option if passed an array
     81             if (o instanceof Array) {
     82                 var options = {};
     83                 $h.each(o, function (option) {
     84                     options[option] = $opt.getOpt(option);
     85                 });
     86                 return options;
     87             }
     88             // Otherwise, just return a simple option
     89             if ($opt instanceof ResumableChunk) {
     90                 if (typeof $opt.opts[o] !== 'undefined') {
     91                     return $opt.opts[o];
     92                 } else {
     93                     $opt = $opt.fileObj;
     94                 }
     95             }
     96             if ($opt instanceof ResumableFile) {
     97                 if (typeof $opt.opts[o] !== 'undefined') {
     98                     return $opt.opts[o];
     99                 } else {
    100                     $opt = $opt.resumableObj;
    101                 }
    102             }
    103             if ($opt instanceof Resumable) {
    104                 if (typeof $opt.opts[o] !== 'undefined') {
    105                     return $opt.opts[o];
    106                 } else {
    107                     return $opt.defaults[o];
    108                 }
    109             }
    110         };
    111 
    112         // EVENTS
    113         // catchAll(event, ...)
    114         // fileSuccess(file), fileProgress(file), fileAdded(file, event), fileRetry(file), fileError(file, message),
    115         // complete(), progress(), error(message, file), pause()
    116         $.events = [];
    117         $.on = function (event, callback) {
    118             $.events.push(event.toLowerCase(), callback);
    119         };
    120         $.fire = function () {
    121             // `arguments` is an object, not array, in FF, so:
    122             var args = [];
    123             for (var i = 0; i < arguments.length; i++) args.push(arguments[i]);
    124             // Find event listeners, and support pseudo-event `catchAll`
    125             var event = args[0].toLowerCase();
    126             for (var i = 0; i <= $.events.length; i += 2) {
    127                 if ($.events[i] == event) $.events[i + 1].apply($, args.slice(1));
    128                 if ($.events[i] == 'catchall') $.events[i + 1].apply(null, args);
    129             }
    130             if (event == 'fileerror') $.fire('error', args[2], args[1]);
    131             if (event == 'fileprogress') $.fire('progress');
    132         };
    133 
    134 
    135         // INTERNAL HELPER METHODS (handy, but ultimately not part of uploading)
    136         var $h = {
    137             stopEvent: function (e) {
    138                 e.stopPropagation();
    139                 e.preventDefault();
    140             },
    141             each: function (o, callback) {
    142                 if (typeof (o.length) !== 'undefined') {
    143                     for (var i = 0; i < o.length; i++) {
    144                         // Array or FileList
    145                         if (callback(o[i]) === false) return;
    146                     }
    147                 } else {
    148                     for (i in o) {
    149                         // Object
    150                         if (callback(i, o[i]) === false) return;
    151                     }
    152                 }
    153             },
    154             generateUniqueIdentifier: function (file) {
    155                 var custom = $.getOpt('generateUniqueIdentifier');
    156                 if (typeof custom === 'function') {
    157                     return custom(file);
    158                 }
    159                 var relativePath = file.webkitRelativePath || file.fileName || file.name; // Some confusion in different versions of Firefox
    160                 var size = file.size;
    161                 return (size + '-' + relativePath.replace(/[^0-9a-zA-Z_-]/img, ''));
    162             },
    163             contains: function (array, test) {
    164                 var result = false;
    165 
    166                 $h.each(array, function (value) {
    167                     if (value == test) {
    168                         result = true;
    169                         return false;
    170                     }
    171                     return true;
    172                 });
    173 
    174                 return result;
    175             },
    176             formatSize: function (size) {
    177                 if (size < 1024) {
    178                     return size + ' bytes';
    179                 } else if (size < 1024 * 1024) {
    180                     return (size / 1024.0).toFixed(0) + ' KB';
    181                 } else if (size < 1024 * 1024 * 1024) {
    182                     return (size / 1024.0 / 1024.0).toFixed(1) + ' MB';
    183                 } else {
    184                     return (size / 1024.0 / 1024.0 / 1024.0).toFixed(1) + ' GB';
    185                 }
    186             },
    187             getTarget: function (params) {
    188                 var target = $.getOpt('target');
    189                 if (target.indexOf('?') < 0) {
    190                     target += '?';
    191                 } else {
    192                     target += '&';
    193                 }
    194                 return target + params.join('&');
    195             }
    196         };
    197 
    198         var onDrop = function (event) {
    199             $h.stopEvent(event);
    200             appendFilesFromFileList(event.dataTransfer.files, event);
    201         };
    202         var onDragOver = function (e) {
    203             e.preventDefault();
    204         };
    205 
    206         // INTERNAL METHODS (both handy and responsible for the heavy load)
    207         var appendFilesFromFileList = function (fileList, event) {
    208             // check for uploading too many files
    209             var errorCount = 0;
    210             var o = $.getOpt(['maxFiles', 'minFileSize', 'maxFileSize', 'maxFilesErrorCallback', 'minFileSizeErrorCallback', 'maxFileSizeErrorCallback', 'fileType', 'fileTypeErrorCallback']);
    211             if (typeof (o.maxFiles) !== 'undefined' && o.maxFiles < (fileList.length + $.files.length)) {
    212                 // if single-file upload, file is already added, and trying to add 1 new file, simply replace the already-added file 
    213                 if (o.maxFiles === 1 && $.files.length === 1 && fileList.length === 1) {
    214                     $.removeFile($.files[0]);
    215                 } else {
    216                     o.maxFilesErrorCallback(fileList, errorCount++);
    217                     return false;
    218                 }
    219             }
    220             var files = [];
    221             $h.each(fileList, function (file) {
    222                 var fileName = file.name.split('.');
    223                 var fileType = fileName[fileName.length - 1].toLowerCase();
    224 
    225                 if (o.fileType.length > 0 && !$h.contains(o.fileType, fileType)) {
    226                     o.fileTypeErrorCallback(file, errorCount++);
    227                     return false;
    228                 }
    229 
    230                 if (typeof (o.minFileSize) !== 'undefined' && file.size < o.minFileSize) {
    231                     o.minFileSizeErrorCallback(file, errorCount++);
    232                     return false;
    233                 }
    234                 if (typeof (o.maxFileSize) !== 'undefined' && file.size > o.maxFileSize) {
    235                     o.maxFileSizeErrorCallback(file, errorCount++);
    236                     return false;
    237                 }
    238 
    239                 // directories have size == 0
    240                 if (!$.getFromUniqueIdentifier($h.generateUniqueIdentifier(file))) {
    241                     (function () {
    242                         var f = new ResumableFile($, file);
    243                         window.setTimeout(function () {
    244                             $.files.push(f);
    245                             files.push(f);
    246                             f.container = (typeof event != 'undefined' ? event.srcElement : null);
    247                             $.fire('fileAdded', f, event)
    248                         }, 0);
    249                     })()
    250                 };
    251             });
    252             window.setTimeout(function () {
    253                 $.fire('filesAdded', files)
    254             }, 0);
    255         };
    256 
    257         // INTERNAL OBJECT TYPES
    258         function ResumableFile(resumableObj, file) {
    259             var $ = this;
    260             $.opts = {};
    261             $.getOpt = resumableObj.getOpt;
    262             $._prevProgress = 0;
    263             $.resumableObj = resumableObj;
    264             $.file = file;
    265             $.fileName = file.fileName || file.name; // Some confusion in different versions of Firefox
    266             $.size = file.size;
    267             $.relativePath = file.webkitRelativePath || $.fileName;
    268             $.uniqueIdentifier = $h.generateUniqueIdentifier(file);
    269             $._pause = false;
    270             $.container = '';
    271             $.startchunkindex = 0;
    272 
    273             var _error = false;
    274 
    275             // Callback when something happens within the chunk
    276             var chunkEvent = function (event, message) {
    277                 // event can be 'progress', 'success', 'error' or 'retry'
    278                 switch (event) {
    279                     case 'progress':
    280                         $.resumableObj.fire('fileProgress', $);
    281                         break;
    282                     case 'error':
    283                         $.abort();
    284                         _error = true;
    285                         $.chunks = [];
    286                         $.resumableObj.fire('fileError', $, message);
    287                         break;
    288                     case 'success':
    289                         if (_error) return;
    290                         $.resumableObj.fire('fileProgress', $); // it's at least progress
    291                         if ($.isComplete()) {
    292                             $.resumableObj.fire('fileSuccess', $, message);
    293                         }
    294                         break;
    295                     case 'retry':
    296                         $.resumableObj.fire('fileRetry', $);
    297                         break;
    298                 }
    299             };
    300 
    301             // Main code to set up a file object with chunks,
    302             // packaged to be able to handle retries if needed.
    303             $.chunks = [];
    304             $.abort = function () {
    305                 // Stop current uploads
    306                 var abortCount = 0;
    307                 $h.each($.chunks, function (c) {
    308                     if (c.status() == 'uploading') {
    309                         c.abort();
    310                         abortCount++;
    311                     }
    312                 });
    313                 if (abortCount > 0) $.resumableObj.fire('fileProgress', $);
    314             };
    315             $.cancel = function () {
    316                 // Reset this file to be void
    317                 var _chunks = $.chunks;
    318                 $.chunks = [];
    319                 // Stop current uploads
    320                 $h.each(_chunks, function (c) {
    321                     if (c.status() == 'uploading') {
    322                         c.abort();
    323                         $.resumableObj.uploadNextChunk();
    324                     }
    325                 });
    326                 $.resumableObj.removeFile($);
    327                 $.resumableObj.fire('fileProgress', $);
    328             };
    329             $.retry = function () {
    330                 $.bootstrap();
    331                 var firedRetry = false;
    332                 $.resumableObj.on('chunkingComplete', function () {
    333                     if (!firedRetry) $.resumableObj.upload();
    334                     firedRetry = true;
    335                 });
    336             };
    337             $.bootstrap = function () {
    338                 $.abort();
    339                 _error = false;
    340                 // Rebuild stack of chunks from file
    341                 $.chunks = [];
    342                 $._prevProgress = 0;
    343                 var round = $.getOpt('forceChunkSize') ? Math.ceil : Math.floor;
    344                 var maxOffset = Math.max(round($.file.size / $.getOpt('chunkSize')), 1);
    345                 for (var offset = 0; offset < maxOffset; offset++) {
    346                     (function (offset) {
    347                         window.setTimeout(function () {
    348                             $.chunks.push(new ResumableChunk($.resumableObj, $, offset, chunkEvent));
    349                             $.resumableObj.fire('chunkingProgress', $, offset / maxOffset);
    350                         }, 0);
    351                     })(offset)
    352                 }
    353                 window.setTimeout(function () {
    354                     $.resumableObj.fire('chunkingComplete', $);
    355                 }, 0);
    356             };
    357             $.progress = function () {
    358                 if (_error) return (1);
    359                 // Sum up progress across everything
    360                 var ret = 0;
    361                 var error = false;
    362                 $h.each($.chunks, function (c) {
    363                     if (c.status($.startchunkindex) == 'error') error = true;
    364                     ret += c.progress(true, $.startchunkindex); // get chunk progress relative to entire file
    365                     //console.info(c.progress(true,$.startchunkindex));
    366                 });
    367                 ret = (error ? 1 : (ret > 0.999 ? 1 : ret));
    368                 ret = Math.max($._prevProgress, ret); // We don't want to lose percentages when an upload is paused
    369                 $._prevProgress = ret;
    370                 return (ret);
    371             };
    372             $.isUploading = function () {
    373                 var uploading = false;
    374                 $h.each($.chunks, function (chunk) {
    375                     if (chunk.status() == 'uploading') {
    376                         uploading = true;
    377                         return (false);
    378                     }
    379                 });
    380                 return (uploading);
    381             };
    382             $.isComplete = function () {
    383                 var outstanding = false;
    384                 $h.each($.chunks, function (chunk) {
    385                     var status = chunk.status();
    386                     if (status == 'pending' || status == 'uploading' || chunk.preprocessState === 1) {
    387                         outstanding = true;
    388                         return (false);
    389                     }
    390                 });
    391                 return (!outstanding);
    392             };
    393             $.pause = function (pause) {
    394                 if (typeof (pause) === 'undefined') {
    395                     $._pause = ($._pause ? false : true);
    396                 } else {
    397                     $._pause = pause;
    398                 }
    399             };
    400             $.isPaused = function () {
    401                 return $._pause;
    402             };
    403 
    404 
    405             // Bootstrap and return
    406             $.resumableObj.fire('chunkingStart', $);
    407             $.bootstrap();
    408             return (this);
    409         }
    410 
    411         function ResumableChunk(resumableObj, fileObj, offset, callback) {
    412             var $ = this;
    413             $.opts = {};
    414             $.getOpt = resumableObj.getOpt;
    415             $.resumableObj = resumableObj;
    416             $.fileObj = fileObj;
    417             $.fileObjSize = fileObj.size;
    418             $.fileObjType = fileObj.file.type;
    419             $.offset = offset;
    420             $.callback = callback;
    421             $.lastProgressCallback = (new Date);
    422             $.tested = false;
    423             $.retries = 0;
    424             $.pendingRetry = false;
    425             $.preprocessState = 0; // 0 = unprocessed, 1 = processing, 2 = finished      
    426 
    427             // Computed properties
    428             var chunkSize = $.getOpt('chunkSize');
    429             $.loaded = 0;
    430             $.startByte = $.offset * chunkSize;
    431             $.endByte = Math.min($.fileObjSize, ($.offset + 1) * chunkSize);
    432             if ($.fileObjSize - $.endByte < chunkSize && !$.getOpt('forceChunkSize')) {
    433                 // The last chunk will be bigger than the chunk size, but less than 2*chunkSize
    434                 $.endByte = $.fileObjSize;
    435             }
    436             $.xhr = null;
    437 
    438             // test() makes a GET request without any data to see if the chunk has already been uploaded in a previous session
    439             $.test = function () {
    440                 // Set up request and listen for event
    441                 $.xhr = new XMLHttpRequest();
    442 
    443                 var testHandler = function (e) {
    444                     $.tested = true;
    445                     var status = $.status();
    446                     if (status == 'success') {
    447                         $.callback(status, $.message());
    448                         $.resumableObj.uploadNextChunk();
    449                     } else {
    450                         $.send();
    451                     }
    452                 };
    453                 $.xhr.addEventListener('load', testHandler, false);
    454                 $.xhr.addEventListener('error', testHandler, false);
    455 
    456                 // Add data from the query options
    457                 var params = [];
    458                 var customQuery = $.getOpt('query');
    459                 if (typeof customQuery == 'function') customQuery = customQuery($.fileObj, $);
    460                 $h.each(customQuery, function (k, v) {
    461                     params.push([encodeURIComponent(k), encodeURIComponent(v)].join('='));
    462                 });
    463                 // Add extra data to identify chunk
    464                 params.push(['resumableChunkNumber', encodeURIComponent($.offset + 1)].join('='));
    465                 params.push(['resumableChunkSize', encodeURIComponent($.getOpt('chunkSize'))].join('='));
    466                 params.push(['resumableCurrentChunkSize', encodeURIComponent($.endByte - $.startByte)].join('='));
    467                 params.push(['resumableTotalSize', encodeURIComponent($.fileObjSize)].join('='));
    468                 params.push(['resumableType', encodeURIComponent($.fileObjType)].join('='));
    469                 params.push(['resumableIdentifier', encodeURIComponent($.fileObj.uniqueIdentifier)].join('='));
    470                 params.push(['resumableFilename', encodeURIComponent($.fileObj.fileName)].join('='));
    471                 params.push(['resumableRelativePath', encodeURIComponent($.fileObj.relativePath)].join('='));
    472                 params.push(['resumableTotalChunks', encodeURIComponent($.fileObj.chunks.length)].join('='));
    473                 // Append the relevant chunk and send it
    474                 $.xhr.open('GET', $h.getTarget(params));
    475                 $.xhr.timeout = $.getOpt('xhrTimeout');
    476                 $.xhr.withCredentials = $.getOpt('withCredentials');
    477                 // Add data from header options
    478                 $h.each($.getOpt('headers'), function (k, v) {
    479                     $.xhr.setRequestHeader(k, v);
    480                 });
    481                 $.xhr.send(null);
    482             };
    483 
    484             $.preprocessFinished = function () {
    485                 $.preprocessState = 2;
    486                 $.send();
    487             };
    488 
    489             // send() uploads the actual data in a POST call
    490             $.send = function () {
    491                 var preprocess = $.getOpt('preprocess');
    492                 if (typeof preprocess === 'function') {
    493                     switch ($.preprocessState) {
    494                         case 0:
    495                             preprocess($);
    496                             $.preprocessState = 1;
    497                             return;
    498                         case 1:
    499                             return;
    500                         case 2:
    501                             break;
    502                     }
    503                 }
    504                 if ($.getOpt('testChunks') && !$.tested) {
    505                     $.test();
    506                     return;
    507                 }
    508 
    509                 // Set up request and listen for event
    510                 $.xhr = new XMLHttpRequest();
    511 
    512                 // Progress
    513                 $.xhr.upload.addEventListener('progress', function (e) {
    514                     if ((new Date) - $.lastProgressCallback > $.getOpt('throttleProgressCallbacks') * 1000) {
    515                         $.callback('progress');
    516                         $.lastProgressCallback = (new Date);
    517                     }
    518                     $.loaded = e.loaded || 0;
    519                 }, false);
    520                 $.loaded = 0;
    521                 $.pendingRetry = false;
    522                 $.callback('progress');
    523 
    524                 // Done (either done, failed or retry)
    525                 var doneHandler = function (e) {
    526                     var status = $.status();
    527                     if (status == 'success' || status == 'error') {
    528                         $.callback(status, $.message());
    529                         $.resumableObj.uploadNextChunk();
    530                     } else {
    531                         $.callback('retry', $.message());
    532                         $.abort();
    533                         $.retries++;
    534                         var retryInterval = $.getOpt('chunkRetryInterval');
    535                         if (retryInterval !== undefined) {
    536                             $.pendingRetry = true;
    537                             setTimeout($.send, retryInterval);
    538                         } else {
    539                             $.send();
    540                         }
    541                     }
    542                 };
    543                 $.xhr.addEventListener('load', doneHandler, false);
    544                 $.xhr.addEventListener('error', doneHandler, false);
    545 
    546                 // Set up the basic query data from Resumable
    547                 var query = {
    548                     resumableChunkNumber: $.offset + 1,
    549                     resumableChunkSize: $.getOpt('chunkSize'),
    550                     resumableCurrentChunkSize: $.endByte - $.startByte,
    551                     resumableTotalSize: $.fileObjSize,
    552                     resumableType: $.fileObjType,
    553                     resumableIdentifier: $.fileObj.uniqueIdentifier,
    554                     resumableFilename: $.fileObj.fileName,
    555                     resumableRelativePath: $.fileObj.relativePath,
    556                     resumableTotalChunks: $.fileObj.chunks.length
    557                 };
    558                 // Mix in custom data
    559                 var customQuery = $.getOpt('query');
    560                 if (typeof customQuery == 'function') customQuery = customQuery($.fileObj, $);
    561                 $h.each(customQuery, function (k, v) {
    562                     query[k] = v;
    563                 });
    564 
    565                 var func = ($.fileObj.file.slice ? 'slice' : ($.fileObj.file.mozSlice ? 'mozSlice' : ($.fileObj.file.webkitSlice ? 'webkitSlice' : 'slice'))),
    566                   bytes = $.fileObj.file[func]($.startByte, $.endByte),
    567                   data = null,
    568                   target = $.getOpt('target');
    569 
    570                 if ($.getOpt('method') === 'octet') {
    571                     // Add data from the query options
    572                     data = bytes;
    573                     var params = [];
    574                     $h.each(query, function (k, v) {
    575                         params.push([encodeURIComponent(k), encodeURIComponent(v)].join('='));
    576                     });
    577                     target = $h.getTarget(params);
    578                 } else {
    579                     // Add data from the query options
    580                     data = new FormData();
    581                     $h.each(query, function (k, v) {
    582                         data.append(k, v);
    583                     });
    584                     data.append($.getOpt('fileParameterName'), bytes);
    585                 }
    586 
    587                 $.xhr.open('POST', target);
    588                 $.xhr.timeout = $.getOpt('xhrTimeout');
    589                 $.xhr.withCredentials = $.getOpt('withCredentials');
    590                 // Add data from header options
    591                 $h.each($.getOpt('headers'), function (k, v) {
    592                     $.xhr.setRequestHeader(k, v);
    593                 });
    594                 $.xhr.send(data);
    595             };
    596             $.abort = function () {
    597                 // Abort and reset
    598                 if ($.xhr) $.xhr.abort();
    599                 $.xhr = null;
    600             };
    601             $.status = function (startchunkindex) {
    602 
    603                 if ($.offset < startchunkindex) {
    604                     // console.info($.offset+'success');
    605                     return ('success');
    606 
    607                 }
    608 
    609 
    610                 // Returns: 'pending', 'uploading', 'success', 'error'
    611                 if ($.pendingRetry) {
    612                     // if pending retry then that's effectively the same as actively uploading,
    613                     // there might just be a slight delay before the retry starts
    614                     return ('uploading');
    615                 } else if (!$.xhr) {
    616                     return ('pending');
    617                 } else if ($.xhr.readyState < 4) {
    618                     // Status is really 'OPENED', 'HEADERS_RECEIVED' or 'LOADING' - meaning that stuff is happening
    619                     return ('uploading');
    620                 } else {
    621 
    622 
    623                     if ($.xhr.status == 200) {
    624                         // HTTP 200, perfect
    625                         return ('success');
    626                     } else if ($h.contains($.getOpt('permanentErrors'), $.xhr.status) || $.retries >= $.getOpt('maxChunkRetries')) {
    627                         // HTTP 415/500/501, permanent error
    628                         return ('error');
    629                     } else {
    630                         // this should never happen, but we'll reset and queue a retry
    631                         // a likely case for this would be 503 service unavailable
    632                         $.abort();
    633                         return ('pending');
    634                     }
    635                 }
    636             };
    637             $.message = function () {
    638                 return ($.xhr ? $.xhr.responseText : '');
    639             };
    640             $.progress = function (relative, startchunkindex) {
    641                 if (typeof (relative) === 'undefined') relative = false;
    642                 var factor = (relative ? ($.endByte - $.startByte) / $.fileObjSize : 1);
    643                 if ($.pendingRetry) return (0);
    644                 var s = $.status(startchunkindex);
    645                 switch (s) {
    646                     case 'success':
    647                     case 'error':
    648                         return (1 * factor);
    649                     case 'pending':
    650                         return (0 * factor);
    651                     default:
    652                         return ($.loaded / ($.endByte - $.startByte) * factor);
    653                 }
    654             };
    655             return (this);
    656         }
    657 
    658         // QUEUE
    659         $.uploadNextChunk = function () {
    660             var found = false;
    661 
    662             // In some cases (such as videos) it's really handy to upload the first
    663             // and last chunk of a file quickly; this let's the server check the file's
    664             // metadata and determine if there's even a point in continuing.
    665             if ($.getOpt('prioritizeFirstAndLastChunk')) {
    666                 $h.each($.files, function (file) {
    667                     if (file.chunks.length && file.chunks[0].status() == 'pending' && file.chunks[0].preprocessState === 0) {
    668                         file.chunks[0].send();
    669                         found = true;
    670                         return (false);
    671                     }
    672                     if (file.chunks.length > 1 && file.chunks[file.chunks.length - 1].status() == 'pending' && file.chunks[file.chunks.length - 1].preprocessState === 0) {
    673                         file.chunks[file.chunks.length - 1].send();
    674                         found = true;
    675                         return (false);
    676                     }
    677                 });
    678                 if (found) return (true);
    679             }
    680 
    681             // Now, simply look for the next, best thing to upload
    682             $h.each($.files, function (file) {
    683                 if (file.isPaused() === false) {
    684                     // $h.each(file.chunks, function(chunk){
    685                     //   if(chunk.status()=='pending' && chunk.preprocessState === 0) {
    686                     //     chunk.send();
    687                     //     found = true;
    688                     //     return(false);
    689                     //   }
    690                     //  });
    691                     for (var i = file.startchunkindex; i < file.chunks.length; i++) {
    692 
    693                         if (file.chunks[i].status() == 'pending' && file.chunks[i].preprocessState === 0) {
    694                             file.chunks[i].send();
    695                             found = true;
    696                             return (false);
    697                         }
    698 
    699                     };
    700 
    701                 }
    702                 if (found) return (false);
    703             });
    704             if (found) return (true);
    705 
    706             // The are no more outstanding chunks to upload, check is everything is done
    707             var outstanding = false;
    708             $h.each($.files, function (file) {
    709                 if (!file.isComplete()) {
    710                     outstanding = true;
    711                     return (false);
    712                 }
    713             });
    714             if (!outstanding) {
    715                 // All chunks have been uploaded, complete
    716                 $.fire('complete');
    717             }
    718             return (false);
    719         };
    720 
    721 
    722         // PUBLIC METHODS FOR RESUMABLE.JS
    723         $.assignBrowse = function (domNodes, isDirectory) {
    724             if (typeof (domNodes.length) == 'undefined') domNodes = [domNodes];
    725 
    726             $h.each(domNodes, function (domNode) {
    727                 var input;
    728                 if (domNode.tagName === 'INPUT' && domNode.type === 'file') {
    729                     input = domNode;
    730                 } else {
    731                     input = document.createElement('input');
    732                     input.setAttribute('type', 'file');
    733                     input.style.display = 'none';
    734                     domNode.addEventListener('click', function () {
    735                         input.style.opacity = 0;
    736                         input.style.display = 'block';
    737                         input.focus();
    738                         input.click();
    739                         input.style.display = 'none';
    740                     }, false);
    741                     domNode.appendChild(input);
    742                 }
    743                 var maxFiles = $.getOpt('maxFiles');
    744                 if (typeof (maxFiles) === 'undefined' || maxFiles != 1) {
    745                     input.setAttribute('multiple', 'multiple');
    746                 } else {
    747                     input.removeAttribute('multiple');
    748                 }
    749                 if (isDirectory) {
    750                     input.setAttribute('webkitdirectory', 'webkitdirectory');
    751                 } else {
    752                     input.removeAttribute('webkitdirectory');
    753                 }
    754                 // When new files are added, simply append them to the overall list
    755                 input.addEventListener('change', function (e) {
    756                     appendFilesFromFileList(e.target.files, e);
    757                     e.target.value = '';
    758                 }, false);
    759             });
    760         };
    761         $.assignDrop = function (domNodes) {
    762             if (typeof (domNodes.length) == 'undefined') domNodes = [domNodes];
    763 
    764             $h.each(domNodes, function (domNode) {
    765                 domNode.addEventListener('dragover', onDragOver, false);
    766                 domNode.addEventListener('drop', onDrop, false);
    767             });
    768         };
    769         $.unAssignDrop = function (domNodes) {
    770             if (typeof (domNodes.length) == 'undefined') domNodes = [domNodes];
    771 
    772             $h.each(domNodes, function (domNode) {
    773                 domNode.removeEventListener('dragover', onDragOver);
    774                 domNode.removeEventListener('drop', onDrop);
    775             });
    776         };
    777         $.isUploading = function () {
    778             var uploading = false;
    779             $h.each($.files, function (file) {
    780                 if (file.isUploading()) {
    781                     uploading = true;
    782                     return (false);
    783                 }
    784             });
    785             return (uploading);
    786         };
    787         $.upload = function () {
    788             // Make sure we don't start too many uploads at once
    789             if ($.isUploading()) return;
    790             // Kick off the queue
    791             $.fire('uploadStart');
    792             for (var num = 1; num <= $.getOpt('simultaneousUploads') ; num++) {
    793                 $.uploadNextChunk();
    794             }
    795         };
    796         $.pause = function () {
    797             // Resume all chunks currently being uploaded
    798             $h.each($.files, function (file) {
    799                 file.abort();
    800             });
    801             $.fire('pause');
    802         };
    803         $.cancel = function () {
    804             for (var i = $.files.length - 1; i >= 0; i--) {
    805                 $.files[i].cancel();
    806             }
    807             $.fire('cancel');
    808         };
    809         $.progress = function () {
    810             var totalDone = 0;
    811             var totalSize = 0;
    812             // Resume all chunks currently being uploaded
    813             $h.each($.files, function (file) {
    814                 totalDone += file.progress() * file.size;
    815                 totalSize += file.size;
    816             });
    817             return (totalSize > 0 ? totalDone / totalSize : 0);
    818         };
    819         $.addFile = function (file, event) {
    820             appendFilesFromFileList([file], event);
    821         };
    822         $.removeFile = function (file) {
    823             for (var i = $.files.length - 1; i >= 0; i--) {
    824                 if ($.files[i] === file) {
    825                     $.files.splice(i, 1);
    826                 }
    827             }
    828         };
    829         $.getFromUniqueIdentifier = function (uniqueIdentifier) {
    830             var ret = false;
    831             $h.each($.files, function (f) {
    832                 if (f.uniqueIdentifier == uniqueIdentifier) ret = f;
    833             });
    834             return (ret);
    835         };
    836         $.getSize = function () {
    837             var totalSize = 0;
    838             $h.each($.files, function (file) {
    839                 totalSize += file.size;
    840             });
    841             return (totalSize);
    842         };
    843 
    844         return (this);
    845     };
    846 
    847 
    848     // Node.js-style export for Node and Component
    849     if (typeof module != 'undefined') {
    850         module.exports = Resumable;
    851     } else if (typeof define === "function" && define.amd) {
    852         // AMD/requirejs: Define the module
    853         define(function () {
    854             return Resumable;
    855         });
    856     } else {
    857         // Browser: Expose to window
    858         window.Resumable = Resumable;
    859     }
    860 
    861 })();
    View Code

    css 代码

     1 /* Reset */
     2 body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,form,fieldset,input,textarea,p,blockquote,th,td{margin:0;padding:0;}table{border-collapse:collapse;border-spacing:0;}fieldset,img{border:0;}address,caption,cite,code,dfn,th,var{font-style:normal;font-weight:normal;}ol,ul {list-style:none;}caption,th {text-align:left;}h1,h2,h3,h4,h5,h6{font-size:100%;font-weight:normal;}q:before,q:after{content:'';}abbr,acronym {border:0;}
     3 
     4 /* Baseline */
     5 body, p, h1, h2, h3, h4, h5, h6 {font:normal 12px/1.3em Helvetica, Arial, sans-serif; color:#333; }
     6 h1 {font-size:22px; font-weight:bold;}
     7 h2 {font-size:19px; font-weight:bold;}
     8 h3 {font-size:16px; font-weight:bold;}
     9 h4 {font-size:14px; font-weight:bold;}
    10 h5 {font-size:12px; font-weight:bold;}
    11 p {margin:10px 0;}
    12 
    13 
    14 /*body {text-align:center; margin:40px;}*/
    15 #frame {margin:0 auto; width:560px; text-align:left;}
    16 
    17 
    18 
    19 /* Uploader: Drag & Drop */
    20 .resumable-error {display:none; font-size:14px; font-style:italic;}
    21 .resumable-drop {padding:10px; font-size:16px; text-align:left; color:#666; font-weight:bold;background-color:#eee; border:2px dashed #aaa; border-radius:10px; margin-top:20px; z-index:9999;  height:20px; width:70px;}
    22 .resumable-dragover {padding:30px; color:#555; background-color:#ddd; border:1px solid #999;}
    23 
    24 /* Uploader: Progress bar */
    25 .resumable-progress {margin:30px 0 30px 0; width:100%; display:none;}
    26 .progress-container {height:7px; background:#9CBD94; position:relative; }
    27 .progress-bar {position:absolute; top:0; left:0; bottom:0; background:#45913A; width:0;}
    28 .progress-text {font-size:11px; line-height:9px; padding-left:10px;}
    29 .progress-pause {padding:0 0 0 7px;}
    30 .progress-resume-link {display:none;}
    31 .is-paused .progress-resume-link {display:inline;}
    32 .is-paused .progress-pause-link {display:none;}
    33 .is-complete .progress-pause {display:none;}
    34 
    35 /* Uploader: List of items being uploaded */
    36 .resumable-list {overflow:auto; margin-right:-20px; display:none;}
    37 .uploader-item {width:148px; height:90px; background-color:#666; position:relative; border:2px solid black; float:left; margin:0 6px 6px 0;}
    38 .uploader-item-thumbnail {width:100%; height:100%; position:absolute; top:0; left:0;}
    39 .uploader-item img.uploader-item-thumbnail {opacity:0;}
    40 .uploader-item-creating-thumbnail {padding:0 5px; font-size:9px; color:white;}
    41 .uploader-item-title {position:absolute; font-size:9px; line-height:11px; padding:3px 50px 3px 5px; bottom:0; left:0; right:0; color:white; background-color:rgba(0,0,0,0.6); min-height:27px;}
    42 .uploader-item-status {position:absolute; bottom:3px; right:3px;}
    43 
    44 /* Uploader: Hover & Active status */
    45 .uploader-item:hover, .is-active .uploader-item {border-color:#4a873c; cursor:pointer; }
    46 .uploader-item:hover .uploader-item-title, .is-active .uploader-item .uploader-item-title {background-color:rgba(74,135,60,0.8);}
    47 
    48 /* Uploader: Error status */
    49 .is-error .uploader-item:hover, .is-active.is-error .uploader-item {border-color:#900;}
    50 .is-error .uploader-item:hover .uploader-item-title, .is-active.is-error .uploader-item .uploader-item-title {background-color:rgba(153,0,0,0.6);}
    51 .is-error .uploader-item-creating-thumbnail {display:none;}
    View Code

    图片 resume.png

    图片pause.png

     

  • 相关阅读:
    可能不知道的C#特性
    设计模式の依赖注入
    How to find WWN and WWPN of HBA card in Linux
    fio IO测试工具
    centos/redhat 多路径存储使用 客户端
    centos/redhat 系统误删除逻辑卷之后如何恢复
    How to use lspci, lsscsi, lsusb, and lsblk to get Linux system devices information
    How to Check and Repair EXT4 Filesystem in Linux
    如何在 Linux 上扫描/检测新的 LUN 和 SCSI 磁盘
    小程序开发知识点总结归纳
  • 原文地址:https://www.cnblogs.com/jiebo/p/4300725.html
Copyright © 2020-2023  润新知