說明:Plupload支持多種瀏覽器,多種上傳方式!
一般的WEB方式文件上傳只能使用FileUpload控件進行一個文件一個文件的進行上傳,就算是批量上傳,也要把文件一個一個的添加到頁面,無法如 windows程序一樣,一次選擇多個文件進行批量上傳。這樣在某些應用上就顯得很不人性化,有時候客戶希望能夠一次選擇很多文件,然后讓系統把選擇的文 件全部上傳。本人在2010年時使用swfupload為核心進行文件的批量上傳的解決方案。見文章:WEB版一次選擇多個文件進行批量上傳(swfupload)的解決方案。
由於上一個swfupload示例對於IE9的兼容性的不太好,以及隨着HTML5與IE9、IE10的逐漸普及,加上鑒於swfupload已經很久沒有進行過更新等等原因,要對批量文件上傳的方案要進行更新,使用新的解決方案。於是在經過一陣尋找之后,決定使用plupload做為核心重新寫了一個批量文件上傳解決方案。
Plupload 是一個Web瀏覽器上的界面友好的文件上傳組件,可顯示上傳進度、圖像自動縮略和上傳分塊,同時上傳多個文件。Plupload 的上傳文件的引擎使用Flash,Silverlight,HTML5,Gears,BrowserPlus或正常的FileUpload。
Plupload組件是由TinyMCE開發者開發的Web文件上傳組件,是一個高度可用的上傳處理組件方便您添加到您的內容管理系統或類似的系統。Plupload目前分為核心API和一個jQuery上傳隊列組件,這使您可以使用現在組件或自己編寫自己的自定義實現。Plupload使用GPLv2許可。
關於Plupload的功能說明:
| Feature |
Flash |
Gears |
HTML 5 |
Silverlight |
BrowserPlus |
HTML 4 |
| Chunking |
√ |
√ |
√1 |
√ |
√ |
X |
| Drag/Drop |
X |
√ |
√2 |
X |
√ |
X |
| PNG Resize |
√ |
√ |
√3 |
√ |
√ |
X |
| JPEG Resize |
√ |
√ |
√3 |
√ |
√ |
X |
| Type filtering |
√ |
√ |
√4 |
√ |
√ |
X |
| Stream upload |
√ |
√ |
√ |
√ |
X |
X |
| Multipart upload |
√ |
√ |
√5 |
√ |
√ |
√ |
| File size restriction |
√ |
√ |
√ |
√ |
√ |
X |
| Upload progress |
√ |
√ |
√ |
√ |
√ |
X |
| Custom headers |
√ |
√ |
√ |
√ |
X |
X |
關於上表中的一些注意點說明:
1.Chunking is properly supported in Chrome. On most part in Firefox 4+.
分塊功能支持的瀏覽器有:chrome,firefox 4以上版本
2.Drag/drop support of files is currently only available in Firefox and WebKit. Safari on Windows has some strange problems and requires workaround.
文件拖放功能目錄只適用於Firefox和WebKit。Safari在Windows上有一些奇怪的問題,需要解決。
3.Image resizing is only possible on Firefox 3.5+ (with fixed quality) and Chrome. Safari/Opera doesn't support direct data access to the selected files.
圖像縮放目前只是支持Firefox 3.5 +(固定質量)和Chrome兩個瀏覽器。Safari和Opera不支持直接訪問選定的文件。
4.File type filtering is currently not supported by all browsers. But we fill the HTML 5 accept attribute so once the support is there it will work.
文件類型過濾是目前所有的瀏覽器都不支持。但是我們設置了HTML 5接受屬性所以一旦瀏覽器支持,它就會工作。
5. Multipart upload is only supported in Gecko and WebKit.
多部分上傳僅支持在Gecko和WebKit。
關於Plupload的一些說明:
1) Plupload使用jQuery的組件做為選擇文件和上傳文件的隊列組件。
2) Plupload使用Flash,Silverlight,HTML5,Gears,BrowserPlus、FileUpload上傳文件技術引擎。
3) Plupload允許自定義使用Plupload核心API來進行選擇文件與上傳文件。
4) JavaScript用來激活文件選擇對話框。此文件選擇對話框是可以設置允許用戶選擇一個單獨的文件或者是多個文件。 選擇的的文件類型也是可以被限制的,因此用戶只能選擇指定的適當的文件,例如jgp;gif。
5) Plupload允許對上傳過程中的一些事件進行自定義,寫上自己的處理方式。
6) 選定的文件的上傳和它所在頁面、表單是獨立的。每個文件都是單獨上傳的,這就保證了服務端腳本能夠在一個時間點更容易地處理單個文件。具體信息可以訪問Plupload官方網站:http://www.plupload.com/
一: 下面就是利用Plupload 組件,讓客戶一次選擇多個文件,然后將選擇的文件上傳到服務器的批量文件解決方案。
讓我們先來看看客戶端的界面效果圖。(多選文件,批量上傳,上傳進度顯示)
1) 顯示界面:

圖1
2) 進行多文件選擇:

圖2
3) 上傳進度顯示

圖3

圖4
二:具體的代碼與操作步驟:
第一步,要進行下面的過程,必須先准備好Plupload組件。
1) Plupload:大家可以訪問Plupload官方網站:http://www.plupload.com/,在這個網站上可以下載到組件與demo。
第二步,創建應用的目錄結構,我這個示例的目錄結構如圖:
1.主要目錄結構
2. 文件上傳用到的js腳本文件。
3. jquery.ui.plupload目錄中的文件,這個文件實際上就是界面中的顯示信息。
第三步,前台部分准備客戶操作的WEB界面,如下[WebUploadFileTest2.aspx、uploadFiles.ashx]
1) 前台客戶端代碼,其中WebUploadFileTest2.aspx的代碼如下,WebUploadFileTest2.aspx.cs文件中只使用默認的代碼,不用添加任何代碼。
WebUploadFileTest2.aspx
Html代碼
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebUploadFileTest2.aspx.cs" Inherits="WebApplication1.WebUploadFileTest2" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> <title>多文件上傳</title> <!-- Load Queue widget CSS and jQuery --> <style type="text/css">@import url(Scripts/jquery.ui.plupload/css/jquery.ui.plupload.css);</style> <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script> <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.23/jquery-ui.min.js"></script> <link rel="stylesheet" href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.23/themes/base/jquery-ui.css"/> <!-- Third party script for BrowserPlus runtime (Google Gears included in Gears runtime now) --> <script type="text/javascript" src="http://bp.yahooapis.com/2.4.21/browserplus-min.js"></script> <!-- Load plupload and all it's runtimes and finally the jQuery UI queue widget --> <script type="text/javascript" src="Scripts/plupload.full.js"></script> <script type="text/javascript" src="Scripts/jquery.ui.plupload/jquery.ui.plupload.js"></script> <script type="text/javascript"> // Convert divs to queue widgets when the DOM is ready $(function () { $("#uploader").plupload({ // General settings runtimes: 'gears,flash,silverlight,browserplus,html5', // 這里是說用什么技術引擎 url: 'uploadFiles.ashx', // 服務端上傳路徑 max_file_size: '10mb', // 文件上傳最大限制。 chunk_size: '1mb', // 上傳分塊每塊的大小,這個值小於服務器最大上傳限制的值即可。 unique_names: true, // 上傳的文件名是否唯一 // Resize images on clientside if we can //// 是否生成縮略圖(僅對圖片文件有效) resize: { width: 320, height: 240, quality: 90 }, // Specify what files to browse for //// 這個數組是選擇器,就是上傳文件時限制的上傳文件類型 filters: [ { title: "Image files", extensions: "jpg,gif,png" }, { title: "Zip files", extensions: "zip,rar,7z" } ], // Flash settings // plupload.flash.swf 的所在路徑 flash_swf_url: 'Scripts/plupload.flash.swf', // Silverlight settings // silverlight所在路徑 silverlight_xap_url: 'Scripts/plupload.silverlight.xap' }); // Client side form validation $('form').submit(function (e) { var uploader = $('#uploader').plupload('getUploader'); // Files in queue upload them first if (uploader.files.length > 0) { // When all files are uploaded submit form uploader.bind('StateChanged', function () { if (uploader.files.length === (uploader.total.uploaded + uploader.total.failed)) { $('form')[0].submit(); } }); uploader.start(); } else alert('You must at least upload one file.'); return false; }); }); </script> </head> <body> <form id="form1" runat="server"> <div> <h2>一次選擇多個文件進行上傳</h2> </div> <div id="uploader" style="width: 600px"> <p>You browser doesn't have Flash, Silverlight, Gears, BrowserPlus or HTML5 support.</p> </div> </form> </body> </html>
以上代碼最后的顯示結果如圖:

圖8.
2)后台服務器端代碼:uploadFiles.ashx文件中使用默認的代碼,不需要添加任何代碼。uploadFiles.ashx.cs文件的代碼如下:
/// <summary> /// uploadFiles 的摘要說明 /// </summary> public class uploadFiles : IHttpHandler { public void ProcessRequest(HttpContext context) { context.Response.ContentType = "text/plain"; context.Response.Write("Hello World"); UploadFile(context); } public bool IsReusable { get { return false; } } public void UploadFile(HttpContext context) { context.Response.CacheControl = "no-cache"; string s_rpath = FileHelper.GetUploadPath();//@"E:\My Documents\Visual Studio 2008\WebSites\SWFUpload\demos\applicationdemo.net"; string Datedir = DateTime.Now.ToString("yy-MM-dd"); string updir = s_rpath + "\\" + Datedir; string extname = string.Empty; string fullname = string.Empty; string filename = string.Empty; if (context.Request.Files.Count > 0) { try { for (int j = 0; j < context.Request.Files.Count; j++) { HttpPostedFile uploadFile = context.Request.Files[j]; int offset =Convert.ToInt32( context.Request["chunk"]); //當前分塊 int total =Convert.ToInt32(context.Request["chunks"]);//總的分塊數量 string name = context.Request["name"]; //文件沒有分塊 if (total == 1) { if (uploadFile.ContentLength > 0) { if (!Directory.Exists(updir)) { Directory.CreateDirectory(updir); } extname = Path.GetExtension(uploadFile.FileName); fullname = DateTime.Now.Year.ToString() + DateTime.Now.Month.ToString() + DateTime.Now.Day.ToString() + DateTime.Now.Hour.ToString() + DateTime.Now.Minute.ToString() + DateTime.Now.Second.ToString(); filename = uploadFile.FileName; uploadFile.SaveAs(string.Format("{0}\\{1}", updir, filename)); } } else { //文件 分成多塊上傳 fullname = WriteTempFile(uploadFile, offset); if (total-offset==1) { //如果是最后一個分塊文件 ,則把文件從臨時文件夾中移到上傳文件 夾中 System.IO.FileInfo fi = new System.IO.FileInfo(fullname); string oldFullName = string.Format("{0}\\{1}", updir, uploadFile.FileName); FileInfo oldFi = new FileInfo(oldFullName); if (oldFi.Exists) { //文件名存在則刪除舊文件 oldFi.Delete(); } fi.MoveTo(oldFullName); } } } } catch (Exception ex) { context.Response.Write("Message" + ex.ToString()); } } } /// <summary> /// 保存臨時文件 /// </summary> /// <param name="uploadFile"></param> /// <param name="chunk"></param> /// <returns></returns> private string WriteTempFile(HttpPostedFile uploadFile, int chunk) { string tempDir = FileHelper.GetTempPath(); if (!Directory.Exists(tempDir)) { Directory.CreateDirectory(tempDir); } string fullName = string.Format("{0}\\{1}.part", tempDir, uploadFile.FileName); if (chunk==0) { //如果是第一個分塊,則直接保存 uploadFile.SaveAs(fullName); } else { //如果是其他分塊文件 ,則原來的分塊文件,讀取流,然后文件最后寫入相應的字節 FileStream fs = new FileStream(fullName, FileMode.Append); if (uploadFile.ContentLength>0) { int FileLen = uploadFile.ContentLength; byte[] input = new byte[FileLen]; // Initialize the stream. System.IO.Stream MyStream = uploadFile.InputStream; // Read the file into the byte array. MyStream.Read(input, 0, FileLen); fs.Write(input,0,FileLen); fs.Close(); } } return fullName; } }
第四步:文件輔助類
/// <summary> ///FileHelper 的摘要說明 /// </summary> public class FileHelper { public FileHelper() { // //TODO: 在此處添加構造函數邏輯 // } /// <summary> /// 獲取上傳目錄 /// </summary> /// <returns></returns> public static string GetUploadPath() { string path = HttpContext.Current.Server.MapPath("~/"); string dirname = GetDirName(); string uploadDir = path + "\\" + dirname; CreateDir(uploadDir); return uploadDir; } /// <summary> /// 獲取臨時目錄 /// </summary> /// <returns></returns> public static string GetTempPath() { string path = HttpContext.Current.Server.MapPath("~/"); string dirname = GetTempDirName(); string uploadDir = path + "\\" + dirname; CreateDir(uploadDir); return uploadDir; } private static string GetDirName() { return System.Configuration.ConfigurationManager.AppSettings["uploaddir"]; } private static string GetTempDirName() { return System.Configuration.ConfigurationManager.AppSettings["tempdir"]; } public static void CreateDir(string path) { if (!System.IO.Directory.Exists(path)) { System.IO.Directory.CreateDirectory(path); } } }
第五步,在進行上傳之后,圖片文件進行縮略圖保存。如下圖。
圖 9
注釋掉以下語句: // resize: { width: 320, height: 240, quality: 90 }, 之后上傳之后的圖片,plupload組件將不在進行縮略。如下圖。

圖10
第六步:以上都是英文界面,可以添加中文語言包。代碼如下。
<!-- Load Queue widget CSS and jQuery --> <style type="text/css">@import url(Scripts/jquery.ui.plupload/css/jquery.ui.plupload.css);</style> <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script> <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.23/jquery-ui.min.js"></script> <link rel="stylesheet" href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.23/themes/base/jquery-ui.css"/> <!-- Third party script for BrowserPlus runtime (Google Gears included in Gears runtime now) --> <script type="text/javascript" src="http://bp.yahooapis.com/2.4.21/browserplus-min.js"></script> <!-- Load plupload and all it's runtimes and finally the jQuery UI queue widget --> <script type="text/javascript" src="Scripts/plupload.full.js"></script> <script type="text/javascript" src="Scripts/i18n/zh-cn.js"></script> //這一句是重點,添加中文語言包文件 <script type="text/javascript" src="Scripts/jquery.ui.plupload/jquery.ui.plupload.js"></script>
添加中文語言包之后的界面顯示如下圖:

上傳錯誤信息:


demo文件 :批量文件上傳示例
一共有兩個文件 :WebUploadFileTest2.aspx示例是上文中給出的代碼示例文件 。
WebUploadFileTest.aspx是另一個示例文件 。
