使用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({ width: 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

 

posted @ 2015-02-26 10:26  曹杰博  阅读(1548)  评论(1编辑  收藏  举报