使用SWFUpload组件无刷新上传图片
在做项目时,需要用到一个图片的无刷新上传,之前听说过SWFUpload,于是想要通过SWFUpload来进行图片的无刷新上传,由于我的项目属于是ASP.NET项目,所以本文着重讲解ASP.NET 的使用,个人感觉示例基本给的很清晰,参考文档进行开发,并非难事
0. 首先下载swfUpload 包,在下载的包中有samples文件夹,samples下有demos文件夹,打开demos文件夹可看到如下图所示结构
我们待会会用到的包括,swfupload目录下的文件,css不建议使用以避免与自己写的CSS相冲突使得页面布局完全乱掉,如果要添加样式最好自己写
打开 applicationdemo.net目录会看到这样的结构
打开index.html可以看到这样的页面
点击NET2.0下的Application Demo C#项
- 添加资源引用
将要引用的资源包含到项目中(包括swfupload文件夹下的文件与,demo下的资源文件,handlers.js是在demo中js目录下的js文件)
- 首先熟悉demo,将demo中的页面包含到项目中
在Defaut.aspx页面中使用swfUpload组件进行图片的无刷新上传直接运行,看效果,大概了解基本过程
- 修改handlers.js文件
我的项目文件结构大概是这样的
我的处理文件上传的页面是ImageUploadHandler.ashx,获取缩略图的页面是GetThumbHandler.ashx,Thumbnail.cs是基于demo中的文件稍作了改动,个人觉得像这种只处理逻辑功能而不展现页面的最好都用一般处理程序来实现。由于哪个文件处理上传哪个文件生成缩略图已经在handlers.js文件中写死了,所以必须要修改handlers.js文件以能够使页面正常运行
- 最终修改版汇总
-
1 function fileQueueError(file, errorCode, message) { 2 try { 3 var imageName = "error.gif"; 4 var errorName = ""; 5 if (errorCode == SWFUpload.errorCode_QUEUE_LIMIT_EXCEEDED) { 6 errorName = "上传文件过多!"; 7 } 8 9 if (errorName != "") { 10 alert(errorName); 11 return; 12 } 13 14 switch (errorCode) { 15 case SWFUpload.QUEUE_ERROR.ZERO_BYTE_FILE: 16 imageName = "zerobyte.gif"; 17 break; 18 case SWFUpload.QUEUE_ERROR.FILE_EXCEEDS_SIZE_LIMIT: 19 imageName = "toobig.gif"; 20 break; 21 case SWFUpload.QUEUE_ERROR.ZERO_BYTE_FILE: 22 case SWFUpload.QUEUE_ERROR.INVALID_FILETYPE: 23 default: 24 alert(message); 25 break; 26 } 27 //添加图片,注意路径 28 addImage("/swfupload/images/" + imageName); 29 30 } catch (ex) { 31 this.debug(ex); 32 } 33 34 } 35 36 function fileDialogComplete(numFilesSelected, numFilesQueued) { 37 try { 38 if (numFilesQueued > 0) { 39 this.startUpload(); 40 } 41 } catch (ex) { 42 this.debug(ex); 43 } 44 } 45 46 function uploadProgress(file, bytesLoaded) { 47 48 try { 49 var percent = Math.ceil((bytesLoaded / file.size) * 100); 50 51 var progress = new FileProgress(file, this.customSettings.upload_target); 52 progress.setProgress(percent); 53 if (percent === 100) { 54 progress.setStatus("正在创建缩略图..."); 55 progress.toggleCancel(false, this); 56 } else { 57 progress.setStatus("正在上传..."); 58 progress.toggleCancel(true, this); 59 } 60 } catch (ex) { 61 this.debug(ex); 62 } 63 } 64 65 function uploadSuccess(file, serverData) { 66 try { 67 //添加缩略图~~~ 68 addImage("/Handlers/GetThumbHandler.ashx?id=" + serverData); 69 70 var progress = new FileProgress(file, this.customSettings.upload_target); 71 72 progress.setStatus("缩略图创建成功!"); 73 progress.toggleCancel(false); 74 } catch (ex) { 75 this.debug(ex); 76 } 77 } 78 79 function uploadComplete(file) { 80 try { 81 /* I want the next upload to continue automatically so I‘ll call startUpload here */ 82 if (this.getStats().files_queued > 0) { 83 this.startUpload(); 84 } else { 85 var progress = new FileProgress(file, this.customSettings.upload_target); 86 progress.setComplete(); 87 progress.setStatus("图片上传成功"); 88 progress.toggleCancel(false); 89 } 90 } catch (ex) { 91 this.debug(ex); 92 } 93 } 94 95 function uploadError(file, errorCode, message) { 96 var imageName = "error.gif"; 97 var progress; 98 try { 99 switch (errorCode) { 100 case SWFUpload.UPLOAD_ERROR.FILE_CANCELLED: 101 try { 102 progress = new FileProgress(file, this.customSettings.upload_target); 103 progress.setCancelled(); 104 progress.setStatus("上传操作被取消"); 105 progress.toggleCancel(false); 106 } 107 catch (ex1) { 108 this.debug(ex1); 109 } 110 break; 111 case SWFUpload.UPLOAD_ERROR.UPLOAD_STOPPED: 112 try { 113 progress = new FileProgress(file, this.customSettings.upload_target); 114 progress.setCancelled(); 115 progress.setStatus("上传停止!"); 116 progress.toggleCancel(true); 117 } 118 catch (ex2) { 119 this.debug(ex2); 120 } 121 case SWFUpload.UPLOAD_ERROR.UPLOAD_LIMIT_EXCEEDED: 122 imageName = "uploadlimit.gif"; 123 break; 124 default: 125 alert(message); 126 break; 127 } 128 129 addImage("/swfupload/images/" + imageName); 130 131 } catch (ex3) { 132 this.debug(ex3); 133 } 134 135 } 136 137 function addImage(src) { 138 var newImg = document.createElement("img"); 139 newImg.style.margin = "5px"; 140 document.getElementById("thumbnails").appendChild(newImg); 141 if (newImg.filters) { 142 try { 143 newImg.filters.item("DXImageTransform.Microsoft.Alpha").opacity = 0; 144 } catch (e) { 145 // If it is not set initially, the browser will throw an error. This will set it if it is not set yet. 146 newImg.style.filter = ‘progid:DXImageTransform.Microsoft.Alpha(opacity=‘ + 0 + ‘)‘; 147 } 148 } else { 149 newImg.style.opacity = 0; 150 } 151 152 newImg.onload = function () { 153 fadeIn(newImg, 0); 154 }; 155 newImg.src = src; 156 } 157 158 function fadeIn(element, opacity) { 159 var reduceOpacityBy = 5; 160 var rate = 30; // 15 fps 161 162 163 if (opacity < 100) { 164 opacity += reduceOpacityBy; 165 if (opacity > 100) { 166 opacity = 100; 167 } 168 169 if (element.filters) { 170 try { 171 element.filters.item("DXImageTransform.Microsoft.Alpha").opacity = opacity; 172 } catch (e) { 173 // If it is not set initially, the browser will throw an error. This will set it if it is not set yet. 174 element.style.filter = ‘progid:DXImageTransform.Microsoft.Alpha(opacity=‘ + opacity + ‘)‘; 175 } 176 } else { 177 element.style.opacity = opacity / 100; 178 } 179 } 180 181 if (opacity < 100) { 182 setTimeout(function () { 183 fadeIn(element, opacity); 184 }, rate); 185 } 186 } 187 188 /* ****************************************** 189 * FileProgress Object 190 * Control object for displaying file info 191 * ****************************************** */ 192 193 function FileProgress(file, targetID) { 194 this.fileProgressID = "divFileProgress"; 195 196 this.fileProgressWrapper = document.getElementById(this.fileProgressID); 197 if (!this.fileProgressWrapper) { 198 this.fileProgressWrapper = document.createElement("div"); 199 this.fileProgressWrapper.className = "progressWrapper"; 200 this.fileProgressWrapper.id = this.fileProgressID; 201 202 this.fileProgressElement = document.createElement("div"); 203 this.fileProgressElement.className = "progressContainer"; 204 205 var progressCancel = document.createElement("a"); 206 progressCancel.className = "progressCancel"; 207 progressCancel.href = "#"; 208 progressCancel.style.visibility = "hidden"; 209 progressCancel.appendChild(document.createTextNode(" ")); 210 211 var progressText = document.createElement("div"); 212 progressText.className = "progressName"; 213 progressText.appendChild(document.createTextNode(file.name)); 214 215 var progressBar = document.createElement("div"); 216 progressBar.className = "progressBarInProgress"; 217 218 var progressStatus = document.createElement("div"); 219 progressStatus.className = "progressBarStatus"; 220 progressStatus.innerHTML = " "; 221 222 this.fileProgressElement.appendChild(progressCancel); 223 this.fileProgressElement.appendChild(progressText); 224 this.fileProgressElement.appendChild(progressStatus); 225 this.fileProgressElement.appendChild(progressBar); 226 227 this.fileProgressWrapper.appendChild(this.fileProgressElement); 228 229 document.getElementById(targetID).appendChild(this.fileProgressWrapper); 230 fadeIn(this.fileProgressWrapper, 0); 231 232 } else { 233 this.fileProgressElement = this.fileProgressWrapper.firstChild; 234 this.fileProgressElement.childNodes[1].firstChild.nodeValue = file.name; 235 } 236 237 this.height = this.fileProgressWrapper.offsetHeight; 238 239 } 240 FileProgress.prototype.setProgress = function (percentage) { 241 this.fileProgressElement.className = "progressContainer green"; 242 this.fileProgressElement.childNodes[3].className = "progressBarInProgress"; 243 this.fileProgressElement.childNodes[3].style.width = percentage + "%"; 244 }; 245 FileProgress.prototype.setComplete = function () { 246 this.fileProgressElement.className = "progressContainer blue"; 247 this.fileProgressElement.childNodes[3].className = "progressBarComplete"; 248 this.fileProgressElement.childNodes[3].style.width = ""; 249 250 }; 251 FileProgress.prototype.setError = function () { 252 this.fileProgressElement.className = "progressContainer red"; 253 this.fileProgressElement.childNodes[3].className = "progressBarError"; 254 this.fileProgressElement.childNodes[3].style.width = ""; 255 256 }; 257 FileProgress.prototype.setCancelled = function () { 258 this.fileProgressElement.className = "progressContainer"; 259 this.fileProgressElement.childNodes[3].className = "progressBarError"; 260 this.fileProgressElement.childNodes[3].style.width = ""; 261 262 }; 263 FileProgress.prototype.setStatus = function (status) { 264 this.fileProgressElement.childNodes[2].innerHTML = status; 265 }; 266 FileProgress.prototype.toggleCancel = function (show, swfuploadInstance) { 267 this.fileProgressElement.childNodes[0].style.visibility = show ? "visible" : "hidden"; 268 if (swfuploadInstance) { 269 var fileID = this.fileProgressID; 270 this.fileProgressElement.childNodes[0].onclick = function () { 271 swfuploadInstance.cancelUpload(fileID); 272 return false; 273 }; 274 } 275 };
handlers.js
1 <!DOCTYPE html> 2 3 <html xmlns="http://www.w3.org/1999/xhtml"> 4 <head runat="server"> 5 <title>Upload Images</title> 6 <script src="swfupload/swfupload.js"></script> 7 <script src="swfupload/handlers.js"></script> 8 <script> 9 //注:div的id名称最好不要改,要改的话在handlers.js文件中也要进行修改,div的名称已经在handlers.js文件中写死 10 var swfu; 11 window.onload = function () { 12 swfu = new SWFUpload({ 13 // 后台设置,设置处理上传的页面 14 upload_url: "/Handlers/ImageUploadHandler.ashx", 15 // 文件上传大小限制设置 16 file_size_limit: "3 MB", 17 //文件类型设置,多种格式以英文中的分号分开 18 file_types: "*.jpg;*.png", 19 //文件描述,与弹出的选择文件对话框相关 20 file_types_description : "Images file", 21 //设置上传文件数量限制 22 file_upload_limit: "1", 23 24 //事件处理程序,最好不要改,事件处理程序已在handlers.js文件中定义 25 // Event Handler Settings - these functions as defined in Handlers.js 26 // The handlers are not part of SWFUpload but are part of my website and control how 27 // my website reacts to the SWFUpload events. 28 file_queue_error_handler : fileQueueError, 29 file_dialog_complete_handler : fileDialogComplete, 30 upload_progress_handler : uploadProgress, 31 upload_error_handler : uploadError, 32 upload_success_handler : uploadSuccess, 33 upload_complete_handler : uploadComplete, 34 35 // 上传按钮设置 36 button_image_url : "/swfupload/images/XPButtonNoText_160x22.png", 37 button_placeholder_id: "spanButtonPlaceholder", 38 button_width: 160, 39 button_height: 22, 40 button_text : ‘请选择图片 (最大3M)‘, 41 button_text_style : ‘.button { font-family: Helvetica, Arial, sans-serif; font-size: 14pt; } .buttonSmall { font-size: 10pt; }‘, 42 button_text_top_padding: 1, 43 button_text_left_padding: 5, 44 45 // swfupload.swf flash设置 46 flash_url : "/swfupload/swfupload.swf", 47 //自定义的其他设置 48 custom_settings : { 49 upload_target: "divFileProgressContainer" 50 }, 51 // 是否开启调试模式,调试时可以设置为true,发布时设置为false 52 debug: false 53 }); 54 } 55 </script> 56 </head> 57 <body> 58 <form id="form1" runat="server"> 59 <div id="content"> 60 <h2>Upload Images Demo</h2> 61 62 <div id="swfu_container" style="margin: 0px 10px;"> 63 <div> 64 <span id="spanButtonPlaceholder"></span> 65 </div> 66 <div id="divFileProgressContainer" style="height: 75px;"></div> 67 <div id="thumbnails"></div> 68 </div> 69 </div> 70 </form> 71 </body> 72 </html>
html Demo
1 public class ImageUploadHandler : IHttpHandler, IRequiresSessionState 2 { 3 private static Common.LogHelper logger = new Common.LogHelper(typeof(ImageUploadHandler)); 4 public void ProcessRequest(HttpContext context) 5 { 6 context.Response.ContentType = "text/plain"; 7 System.Drawing.Image thumbnail_image = null; 8 System.Drawing.Image original_image = null; 9 System.Drawing.Bitmap final_image = null; 10 System.Drawing.Graphics graphic = null; 11 MemoryStream ms = null; 12 try 13 { 14 if (context.Session["User"]==null) 15 { 16 context.Response.Write("没有上传图片的权限!"); 17 context.Response.End(); 18 return; 19 } 20 // Get the data 21 HttpPostedFile image_upload = context.Request.Files["Filedata"]; 22 //获取文件扩展名 23 string fileExt = System.IO.Path.GetExtension(image_upload.FileName).ToLower(); 24 25 //判断文件扩展名是否符合要求 26 if (fileExt!=".jpg"&&fileExt!=".png") 27 { 28 return; 29 } 30 string contentType = (fileExt == ".jpg" ? "image/jpeg" : "image/png"); 31 //当前时间字符串 32 string timeString = DateTime.Now.ToString("yyyyMMddHHmmssfff"); 33 string path = "/Upload/"+timeString + fileExt; 34 context.Session["imgPath"] = path; 35 //获取、构建要上传文件的物理路径 36 string serverPath = context.Server.MapPath("~/"+path); 37 //保存到服务器 38 image_upload.SaveAs(serverPath); 39 //记录日志 40 logger.Debug("图片上传成功!"); 41 #region 生成缩略图 42 43 // Retrieve the uploaded image 44 original_image = System.Drawing.Image.FromStream(image_upload.InputStream); 45 46 // Calculate the new width and height 47 int width = original_image.Width; 48 int height = original_image.Height; 49 int target_width = 100; 50 int target_height = 100; 51 int new_width, new_height; 52 53 float target_ratio = (float)target_width / (float)target_height; 54 float image_ratio = (float)width / (float)height; 55 56 if (target_ratio > image_ratio) 57 { 58 new_height = target_height; 59 new_width = (int)Math.Floor(image_ratio * (float)target_height); 60 } 61 else 62 { 63 new_height = (int)Math.Floor((float)target_width / image_ratio); 64 new_width = target_width; 65 } 66 67 new_width = new_width > target_width ? target_width : new_width; 68 new_height = new_height > target_height ? target_height : new_height; 69 70 // Create the thumbnail 71 72 final_image = new System.Drawing.Bitmap(target_width, target_height); 73 graphic = System.Drawing.Graphics.FromImage(final_image); 74 graphic.FillRectangle(new System.Drawing.SolidBrush(System.Drawing.Color.Black), new System.Drawing.Rectangle(0, 0, target_width, target_height)); 75 int paste_x = (target_width - new_width) / 2; 76 int paste_y = (target_height - new_height) / 2; 77 graphic.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic; /* new way */ 78 //graphic.DrawImage(thumbnail_image, paste_x, paste_y, new_width, new_height); 79 graphic.DrawImage(original_image, paste_x, paste_y, new_width, new_height); 80 81 // Store the thumbnail in the session (Note: this is bad, it will take a lot of memory, but this is just a demo) 82 ms = new MemoryStream(); 83 final_image.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg); 84 85 #endregion 86 // Store the data in my custom Thumbnail object 87 string thumbnail_id = timeString; 88 Thumbnail thumb = new Thumbnail(thumbnail_id, ms.GetBuffer()) { ContentType= contentType }; 89 context.Session["file_info"] = thumb; 90 context.Response.StatusCode = 200; 91 context.Response.Write(thumb.ID); 92 } 93 catch(Exception ex) 94 { 95 // If any kind of error occurs return a 500 Internal Server error 96 context.Response.StatusCode = 500; 97 logger.Error(ex); 98 } 99 finally 100 { 101 // Diospose 102 if (final_image != null) final_image.Dispose(); 103 if (graphic != null) graphic.Dispose(); 104 if (original_image != null) original_image.Dispose(); 105 if (thumbnail_image != null) thumbnail_image.Dispose(); 106 if (ms != null) ms.Close(); 107 context.Response.End(); 108 } 109 } 110 111 public bool IsReusable 112 { 113 get 114 { 115 return false; 116 } 117 } 118 }
ImageUploadHandler
1 public class GetThumbHandler : IHttpHandler, IRequiresSessionState 2 { 3 4 public void ProcessRequest(HttpContext context) 5 { 6 context.Response.ContentType = "text/plain"; 7 string id = context.Request.QueryString["id"]; 8 if (id == null) 9 { 10 context.Response.StatusCode = 404; 11 context.Response.Write("Not Found"); 12 context.Response.End(); 13 return; 14 } 15 16 Thumbnail thumb= context.Session["file_info"] as Thumbnail; 17 if (thumb.ID == id) 18 { 19 context.Response.ContentType = thumb.ContentType; 20 context.Response.BinaryWrite(thumb.Data); 21 context.Response.End(); 22 return; 23 } 24 25 //没有找到相应图片,返回404 26 context.Response.StatusCode = 404; 27 context.Response.Write("Not Found"); 28 context.Response.End(); 29 } 30 31 public bool IsReusable 32 { 33 get 34 { 35 return false; 36 } 37 } 38 }
GetThumbHandler
1 /// <summary> 2 /// 缩略图 3 /// </summary> 4 public class Thumbnail 5 { 6 public Thumbnail(string id, byte[] data) 7 { 8 this.ID = id; 9 this.Data = data; 10 } 11 12 private string id; 13 public string ID 14 { 15 get 16 { 17 return this.id; 18 } 19 set 20 { 21 this.id = value; 22 } 23 } 24 25 private byte[] thumbnail_data; 26 public byte[] Data 27 { 28 get 29 { 30 return this.thumbnail_data; 31 } 32 set 33 { 34 this.thumbnail_data = value; 35 } 36 } 37 38 private string contentType; 39 public string ContentType 40 { 41 get 42 { 43 return contentType; 44 } 45 46 set 47 { 48 contentType = value; 49 } 50 } 51 }
Thumbnail