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