出於安全效能的考慮,目前js端不支援擷取本地圖片進行預覽,正好在做一款類似於QQ心情的發布框,找了不少jquery外掛程式,沒幾個能滿足需求,因此自己使用SWFuplad來實現這個圖片上傳預覽。
先粘上以下外掛程式,在別的圖片上傳功能說不定各位能用的上。
1、jQuery File Upload
Demo地址:http://blueimp.github.io/jQuery-File-Upload/
優點是使用jquery進行圖片的非同步上傳,可控性好,可根據自己的需求任意定製;
缺點是在IE9等一些瀏覽器中,不支援圖片預覽,圖片選擇框中不支援多檔案選擇(這點是我拋棄它的原因);
2、CFUpdateDemo地址:http://www.access2008.cn/update/優點:使用js+flash實現,相容所有瀏覽器,優點介面效果還可以,支援批量上傳、支援預覽、進度條、刪除等功能,作為圖片的上傳控制項非常好用;缺點:定製型外掛程式,只能修改顏色,樣式已經固定死了;3、SWFUpload:http://code.google.com/p/swfupload/中文文檔協助地址:http://www.phptogether.com/swfuploadoc/#uploadError本文所使用的就是此外掛程式,使用flash+jquery實現,可以更改按鈕及各種樣式;監聽事件也很全。
以下貼出源碼及設計思路,主要功能點包括:
1、圖片的上傳預覽(先將圖片上傳至伺服器,然後再返回地址預覽,目前拋開html5比較靠譜的預覽方式)2、縮圖的產生(等比例縮放後再截取中間地區作為縮圖,類似QQ空間的做法,不過貌似QQ空間加入了Face Service的功能)以下是此次實現的功能:
1、Thumbnail.cs
public class Thumbnial { /// <summary> /// 產生縮圖 /// </summary> /// <param name="imgSource">原圖片</param> /// <param name="newWidth">縮圖寬度</param> /// <param name="newHeight">縮圖高度</param> /// <param name="isCut">是否裁剪(以中心點)</param> /// <returns></returns> public static Image GetThumbnail(System.Drawing.Image imgSource, int newWidth, int newHeight, bool isCut) { int rWidth = 0; // 等比例縮放後的寬度 int rHeight = 0; // 等比例縮放後的高度 int sWidth = imgSource.Width; // 原圖片寬度 int sHeight = imgSource.Height; // 原圖片高度 double wScale = (double)sWidth / newWidth; // 寬比例 double hScale = (double)sHeight / newHeight; // 高比例 double scale = wScale < hScale ? wScale : hScale; rWidth = (int)Math.Floor(sWidth / scale); rHeight = (int)Math.Floor(sHeight / scale); Bitmap thumbnail = new Bitmap(rWidth, rHeight); try { // 如果是截取原圖,並且原圖比例小於所要截取的矩形框,那麼保留原圖 if (!isCut && scale <= 1) { return imgSource; } using (Graphics tGraphic = Graphics.FromImage(thumbnail)) { tGraphic.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic; /* new way */ Rectangle rect = new Rectangle(0, 0, rWidth, rHeight); Rectangle rectSrc = new Rectangle(0, 0, sWidth, sHeight); tGraphic.DrawImage(imgSource, rect, rectSrc, GraphicsUnit.Pixel); } if (!isCut) { return thumbnail; } else { int xMove = 0; // 向右位移(裁剪) int yMove = 0; // 向下位移(裁剪) xMove = (rWidth - newWidth) / 2; yMove = (rHeight - newHeight) / 2; Bitmap final_image = new Bitmap(newWidth, newHeight); using (Graphics fGraphic = Graphics.FromImage(final_image)) { fGraphic.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic; /* new way */ Rectangle rect1 = new Rectangle(0, 0, newWidth, newHeight); Rectangle rectSrc1 = new Rectangle(xMove, yMove, newWidth, newHeight); fGraphic.DrawImage(thumbnail, rect1, rectSrc1, GraphicsUnit.Pixel); } thumbnail.Dispose(); return final_image; } } catch (Exception e) { return new Bitmap(newWidth, newHeight); } } }
2、圖片上傳處理常式Upload.ashx
using System;using System.Collections.Generic;using System.Linq;using System.Web;using System.Drawing;namespace Mood{ /// <summary> /// Upload 的摘要說明 /// </summary> public class Upload : IHttpHandler { Image thumbnail; public void ProcessRequest(HttpContext context) { context.Response.ContentType = "text/plain"; try { string id = System.Guid.NewGuid().ToString(); HttpPostedFile jpeg_image_upload = context.Request.Files["Filedata"]; Image original_image = System.Drawing.Image.FromStream(jpeg_image_upload.InputStream); original_image.Save(System.Web.HttpContext.Current.Server.MapPath("~/Files/" + id + ".jpg")); int target_width = 200; int target_height = 150; string path = "Files/Files200/" + id + ".jpg"; string saveThumbnailPath = System.Web.HttpContext.Current.Server.MapPath("~/" + path); thumbnail = Thumbnial.GetThumbnail(original_image, target_width, target_height, true); thumbnail.Save(saveThumbnailPath,System.Drawing.Imaging.ImageFormat.Jpeg); context.Response.Write(path); } catch (Exception e) { // If any kind of error occurs return a 500 Internal Server error context.Response.StatusCode = 500; context.Response.Write("上傳過程中出現錯誤!"); } finally { if (thumbnail != null) { thumbnail.Dispose(); } } } public bool IsReusable { get { return false; } } }}
3、前台介面Mood.aspx
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Mood.aspx.cs" Inherits="Mood.Mood" %><!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"> <script src="SwfUpload/swfupload.js" type="text/javascript"></script> <script src="jquery-1.7.1.js" type="text/javascript"></script> <link href="Style/Mood.css" rel="stylesheet" type="text/css" /> <title></title> <script type="text/javascript"> $().ready(function () { SetSwf(); $("#btnReply").click(function () { $("#divImgs").hide(); }); }); var swfu; function SetSwf() { swfu = new SWFUpload({ // Backend Settings upload_url: "Upload.ashx", // File Upload Settings file_size_limit: "20 MB", file_types: "*.jpg;*.png;*jpeg;*bmp", file_types_description: "JPG;PNG;JPEG;BMP", file_upload_limit: "0", // Zero means unlimited 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 settings button_image_url: "/Style/Image/4-16.png", button_placeholder_id: "divBtn", button_width: 26, button_height: 26, // Flash Settings flash_url: "/swfupload/swfupload.swf", custom_settings: { upload_target: "divFileProgressContainer" }, // Debug Settings debug: false }); } // 檔案校正 function fileQueueError(file, errorCode, message) { try { switch (errorCode) { case SWFUpload.QUEUE_ERROR.ZERO_BYTE_FILE: alert("上傳檔案有錯誤!"); break; case SWFUpload.QUEUE_ERROR.FILE_EXCEEDS_SIZE_LIMIT: alert("上傳檔案超過限制(20M)!"); break; case SWFUpload.QUEUE_ERROR.ZERO_BYTE_FILE: case SWFUpload.QUEUE_ERROR.INVALID_FILETYPE: default: alert("檔案出現錯誤!"); break; } } catch (ex) { this.debug(ex); } } // 檔案選擇完畢時觸發 function fileDialogComplete(numFilesSelected, numFilesQueued) { try { if (numFilesQueued > 0) { $("#divImgs").show(); for (var i = 0; i < numFilesQueued; i++) { $("#ulUpload").append('<li id="li' + i + '"><img class="imgload" src="/style/image/loading.gif" alt="" /></li>'); } this.startUpload(); } } catch (ex) { this.debug(ex); } } // 捲軸的處理方法 暫時沒寫 function uploadProgress(file, bytesLoaded) { } // 每個檔案上傳成功後的處理 function uploadSuccess(file, serverData) { try { var index = file.id.substr(file.id.lastIndexOf('_') + 1); $("#li" + index).html(""); $("#li" + index).html('<img src="' + serverData + '" alt=""/>'); index++; } catch (ex) { this.debug(ex); } } // 上傳完成後,觸發下一個檔案的上傳 function uploadComplete(file) { try { if (this.getStats().files_queued > 0) { this.startUpload(); } } catch (ex) { this.debug(ex); } } // 單個檔案上傳錯誤時處理 function uploadError(file, errorCode, message) { var imageName = "imgerror.png"; try { var index = file.id.substr(file.id.lastIndexOf('_') + 1); $("#li" + index).html(""); $("#li" + index).html('<img src="/style/image/imgerror.png" alt=""/>'); index++; } catch (ex3) { this.debug(ex3); } } </script></head><body> <form id="form1" runat="server"> <div style="width: 600px;"> <div class="divTxt"> 文字框 </div> <div style="height: 30px; line-height: 30px;"> <div id="divBtn" style="float: left; width: 26px; height: 26px;"> </div> <div style="float: right;"> <input id="btnReply" type="button" value="發表" /> </div> </div> <div id="divImgs" style="border: 1px solid #cdcdcd; display: none;"> <div> 上傳圖片</div> <ul id="ulUpload" class="ulUpload"> </ul> </div> </div> </form></body></html>
使用Vs2010開發,以下為項目源碼地址:http://download.csdn.net/detail/wuwo333/5944249
在源碼中,bitmap在儲存時,沒有設定儲存參數(System.Drawing.Imaging.ImageFormat.Jpeg)造成縮圖檔案過大!源碼中有此失誤,請大家注意!