在這之前在感謝園子好多大牛的文章,在這里就不列出來了。
進入正題。
svn檢索https://github.com/moxiecode/plupload 獲取到代碼,這篇文章使用的是v2.1.8
主要功能:
1、多文件上傳
2、分片上傳
3、顯示進度條
先看看項目結構



<style> .trip-uploader .webuploader-container { float: left; position: relative; width: 20%; display: block; line-height: 1.4; background: #fff; border: 1px dashed #D2D1D6; border-radius: 6px; color: #ccc; padding: 15px 0; font-size: 13px; text-align: center; margin: 4px; cursor: pointer; } .webuploader-pick { width: 100%; display: block; cursor: pointer; overflow: hidden; } .trip-uploader .webuploader-container .icon-plus { width: 32px; height: 32px; display: block; margin: 10px auto; background: url(/images/upimagedefault.png) no-repeat; background-size: 32px; } .upload-btn { position: absolute; top: 0px; left: 0px; width: 100%; height: 98%; overflow: hidden; z-index: 0; } .file-item { width: 120px; height: 120px; float: left; position: relative; margin: 0 0 10px; padding: 4px; padding: 4px; line-height: 1.42857143; background-color: #fff; border: 1px solid #ddd; border-radius: 4px; -webkit-transition: border .2s ease-in-out; -o-transition: border .2s ease-in-out; transition: border .2s ease-in-out; } .fancybox { display: block; overflow: hidden; background: #eee; height: 120px; } .file-item img { height: 110px; } .file-item .progress { position: absolute; right: 4px; bottom: 4px; left: 4px; height: 4px; overflow: hidden; z-index: 15; margin: 0; padding: 0; border-radius: 0; background: 0 0; } .file-item .progress span { display: block; overflow: hidden; width: 0; height: 100%; background: url(/images/progress.png) repeat-x #06BD01; -webit-transition: width .2s linear; -moz-transition: width .2s linear; -o-transition: width .2s linear; -ms-transition: width .2s linear; transition: width .2s linear; -webkit-animation: progressmove 2s linear infinite; -moz-animation: progressmove 2s linear infinite; -o-animation: progressmove 2s linear infinite; -ms-animation: progressmove 2s linear infinite; animation: progressmove 2s linear infinite; -webkit-transform: translateZ(0); } </style>
<form id="form1" runat="server"> <div> <div class="trip-uploader" style="height: 160px;"> <div class="uploader-images-list"> </div> <div class="webuploader-container"> <div id="coverPicker" class="webuploader-pick webuploader-pick-hover" style="position: relative;"> <i class="icon icon-plus"></i>上傳圖片<br /> (最多N張) </div> <div id="imgupload" class="upload-btn"></div> </div> </div> </div> </form>
<script>
var $list = $(".uploader-images-list");
var uploader = new plupload.Uploader({ //實例化一個plupload上 傳對象
browse_button: 'imgupload',
runtimes: 'html5,flash,silverlight,html4',
url: '/Core/UploadHandler.ashx',
flash_swf_url: '/js/plupload/Moxie.swf',
silverlight_xap_url: '/js/plupload/Moxie.xap',
filters: {
mime_types: [ //只允許上傳圖片文件
{ title: "圖片文件", extensions: "jpg,gif,png" }
]
}
, prevent_duplicates: !1
, max_file_size: '10mb'
, chunk_size: '1mb'//分片上傳一定要注意壓縮的大小
//, resize: { width: 320, height: 240, quality: 90 }
, init:
{
PostInit: function (a) {
console.log("初始化完畢");
},
FilesAdded: function (uder, files) {
console.log("添加進隊列");
for (var i = 0; i < files.length; i++) {
var file = files[i];
appendimg(file.id);
}
uder.start();
},
BeforeUpload: function (uder, files) {
console.log("開始上傳");
},
UploadProgress: function (uder, file) {
console.log("進度:[百分比:" + file.percent + ",狀態:" + file.status + ",原始大小:" + file.origSize + ",已傳:" + file.loaded + "]");
progress(file.id, file.percent);
},
UploadFile: function (uder) {
console.log(uder.id + "開始上傳");
},
FileUploaded: function (uder, file, resObject) {
var result = resObject.response;
console.log("上傳完成" + result);
var $fileitem = $("." + file.id)
$fileitem.find("img").attr("src", JSON.parse(result).data);
//移除進度條
$fileitem.find(".progress").remove();
},
ChunkUploaded: function (a, b, c) {
console.log("小片上傳完成后");
},
UploadComplete: function (uder, files) {
alert("上傳完畢");
},
Error: function () {
alert("ERROR");
}
}
});
uploader.init(); //初始化
function appendimg(id, imgurl) {
var html = ' <div class="' + id + ' file-item"><a class="fancybox"> <img /> </a> </div>';
$(".uploader-images-list").append(html);
}
function progress(id, percent) {
var c = $list.find("." + id);
var d = c.find(".progress span");
d.length || (d = $('<p class="progress"><span></span></p>').appendTo(c).find("span"));
d.css("width", percent + "%")
}
</script>
下面的是后台代碼:
/// <summary> /// BaseHandler 的摘要說明 /// </summary> public class BaseHandler : IHttpHandler, IRequiresSessionState { public HttpRequest Request { get { return HttpContext.Current.Request; } } public HttpResponse Response { get { return HttpContext.Current.Response; } } public void ProcessRequest(HttpContext context) { var data = ProcessResponse(context); var newData = new { code = data.code, data = data.data, msg = data.msg }; context.Response.ContentType = "application/json"; string jsonData = JsonConvert.SerializeObject(newData); context.Response.Write(jsonData); } /// <summary> /// 定義輸出函數 /// </summary> /// <returns></returns> protected virtual ResponseData ProcessResponse(HttpContext context) { ResponseData data = new ResponseData { code = ReturnCode.error, data = "" }; return data; } public bool IsReusable { get { return false; } } } /// <summary> /// 返回值 /// </summary> public struct ResponseData { /// <summary> /// 返回的狀態碼 /// </summary> public ReturnCode code; /// <summary> /// 返回狀態碼對應的消息 /// </summary> public string msg; /// <summary> /// 附加內容 /// </summary> public object data; } /// <summary> /// 操作代碼 返回給前台JS /// </summary> public enum ReturnCode { /// <summary> /// 失敗 0 /// </summary> error = 0, /// <summary> /// 成功 1 /// </summary> success = 1, /// <summary> /// 其他 ,自定義狀態 返回9 /// </summary> other = 9 }
public class UploadHandler : BaseHandler { ResponseData responseData = new ResponseData() { code = ReturnCode.error, msg = "未配置", data = null }; protected override ResponseData ProcessResponse(HttpContext context) { Response.CacheControl = "no-cache"; string dir = GetUploadPath(); if (Request.Files.Count > 0) { try { for (int j = 0; j < Request.Files.Count; j++) { int offset = Convert.ToInt32(Request["chunk"]); //當前分塊 int total = Convert.ToInt32(Request["chunks"]);//總的分塊數量 string name = Request["name"]; HttpPostedFile uploadFile = Request.Files[j]; if (total == 1) { if (uploadFile.ContentLength > 0) { string extname = Path.GetExtension(uploadFile.FileName);//.jpg string filename = uploadFile.FileName; //xx.jpg string path = dir + RndNum(6) + extname; uploadFile.SaveAs(context.Server.MapPath(path)); responseData.msg = "上傳成功"; responseData.data = path; } } else { //文件 分成多塊上傳 string tempPath = WriteTempFile(uploadFile, offset); if (total - offset == 1) { //如果是最后一個分塊文件 ,則把文件從臨時文件夾中移到上傳文件夾中 string extname = Path.GetExtension(name);//.jpg string newPath = dir + RndNum(6) + extname; System.IO.FileInfo fi = new System.IO.FileInfo(context.Server.MapPath(tempPath));//臨時文件名 //把臨時文件移動到新目錄並重名 fi.MoveTo(context.Server.MapPath(newPath)); responseData.msg = "上傳成功"; responseData.data = newPath; } else { responseData.msg = "上傳成功"; responseData.data = tempPath; } } } } catch (Exception ex) { responseData.msg = ex.Message; responseData.data = ex.ToString(); } } return responseData; } /// <summary> /// 保存臨時文件-返回相對路徑 /// </summary> /// <param name="uploadFile">文件流</param> /// <param name="chunk">第幾個分塊 從0開始</param> /// <param name="context"></param> /// <returns></returns> private string WriteTempFile(HttpPostedFile uploadFile, int chunk) { string tempPath = GetTempPath() + uploadFile.FileName + ".part"; //臨時相對路徑 string saveTempPath = HttpContext.Current.Server.MapPath(tempPath); if (chunk == 0) { uploadFile.SaveAs(saveTempPath); //如果是第一個分塊,則直接保存 } else { //如果是其他分塊文件 ,則原來的分塊文件,讀取流,然后文件最后寫入相應的字節 FileStream fs = new FileStream(saveTempPath, FileMode.Append); if (uploadFile.ContentLength > 0) { int FileLen = uploadFile.ContentLength; byte[] input = new byte[FileLen]; System.IO.Stream MyStream = uploadFile.InputStream; MyStream.Read(input, 0, FileLen); fs.Write(input, 0, FileLen); fs.Close(); } } return tempPath; } /// <summary> /// 該方法用於生成指定位數的隨機數 /// </summary> /// <param name="VcodeNum">參數是隨機數的位數</param> /// <returns>返回一個隨機數字符串</returns> public string RndNum(int VcodeNum) { string Vchar = "0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f,g,h,i,j,k,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D,E,F,G,H,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z"; //string Vchar = "0,1,2,3,4,5,6,7,8,9"; string[] VcArray = Vchar.Split(',');//拆分成數組 string VNum = ""; seed++; Random rand = new Random(seed); for (int i = 0; i < VcodeNum; i++) { VNum += VcArray[rand.Next(VcArray.Length - 1)]; } return VNum; } private static int _seed = int.Parse(DateTime.Now.Ticks.ToString().Substring(10)); private static int seed { get { return _seed; } set { _seed = value; } } //獲取存放路徑 public static string GetUploadPath() { string path = HttpContext.Current.Server.MapPath("/upload/"); if (!System.IO.Directory.Exists(path)) { System.IO.Directory.CreateDirectory(path); } return "/upload/"; } /// <summary> /// 獲取臨時目錄 相對路徑 /// </summary> /// <returns></returns> public static string GetTempPath() { string path = GetUploadPath(); path = HttpContext.Current.Server.MapPath("/upload/temp/"); if (!System.IO.Directory.Exists(path)) { System.IO.Directory.CreateDirectory(path); } return "/upload/temp/"; } }
源代碼:
