Asp.Net無刷新上傳并裁剪頭像
開發網站幾乎都做過上傳圖片并截圖,做個無刷新Asp.Net上傳并截圖示例
實現功能:
1.選擇文件,自動上傳并生成縮放圖(上傳帶進度條),形成預覽圖
2.在預覽區,實現鼠標拖拽截圖區,截取圖片(示例截圖區按縮放圖小邊為截圖正方形長度,可擴展為截圖區可變形式)
3.點擊保存,截取小圖,保存截取圖并顯示在頁面上,并刪除原縮略圖
示例截圖:


-------------------------------------------------------------------------------風騷分隔線-----------------------------------------------------------------------------------------------
| 第一步:準備工作,認識一些必要的東西 |
1.無刷新上傳借助于Uploadify這個基于Flash的支持多文件上傳的Jquery插件,很多人估計都用過了,我也在不同的項目中用過很多次,簡單易用且功能強大
(美中不足,插件本身對session使用有一點BUG,不過能解決,chrome&FireFox里上傳如果代碼中有用Session,獲取不到)
沒用過這個插件的可以去它的官網認識一下這個插件
Uploadify官網:
uploadify下載: (本示例用:Uploadify-v2.1.4.zip)
http://www.uploadify.com/download/
uploady全屬性、事件、方法介紹:
http://www.uploadify.com/documentation/
這里對一些常用介紹一下:
| 名稱 | 介紹 | 類型 |
| Uploadify常用屬性 | ||
| uploader | uploadify的swf文件的路徑 | string |
| cancelImg | 取消按鈕圖片路徑 | string |
| folder | 上傳文件夾路徑 | string |
| multi | 是否多文件上傳 | boolean |
| script | 上傳文件處理代碼的文件路徑 | json |
| scriptData | 提交到script對應路徑文件的參數 | 類型 |
| method | 提交scriptData的方式(get/post) | string |
| fileExt | 支持上傳文件類型(格式:*.jpg;*.png) | string |
| fileDesc | 提示于點擊上傳彈出選擇文件框文件類型(自定義) | string |
| sizeLimit | 上傳大小限制(byte為單位) | integer |
| auto | 是否選擇文件后自動上傳 | boolean |
| Uploadify常用事件 | ||
| onAllComplete | 上傳完成后響應 | function |
| onCancel | 取消時響應 | function |
| Uploadify常用方法 | ||
| .uploadify() | 初始化uploadify上傳 | |
| .uploadifyUpload() | 觸發上傳 | |
| .uploadifySettings() | 更新uploadify的屬性 | |
2.裁剪圖片使用CutPic.js (這個JS文件如果各位要用,要自己用心看看,注釋很詳細了)
源碼太長,這里不貼出來,后面會提供下載
顯示圖片也用的CutPic里的方法
JS代碼顯示
function ShowImg(imagePath,imgWidth,imgHeight) {
var imgPath = imagePath != "" ? imagePath : "!images/ef_pic.jpg";
var ic = new ImgCropper("bgDiv", "dragDiv", imgPath, imgWidth, imgHeight, null);
}
HTML顯示部分布局(一個嵌套層級關系,外面是顯示圖片,里面dragDiv是拖拽層)
<div id="bgDiv">
<div id="dragDiv">
</div>
</div>
| 第二步:引用資源,開始編寫 |
Default.aspx頁
用了三個隱藏域去存截圖區的左上角X坐標,Y坐禁,以及截圖框的大小;
這個要修改CutPic里設置切割要用到,CutPic.js里己經做了注釋;
Uploadify中參數如果動態改變的,可以寫在像我下面寫的這樣去更新參數
$("#uploadify").uploadifySettings('scriptData',{'LastImgUrl':$('#hidImageUrl').val()}); //更新參數
View Code
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default"%>
<!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>Posrchev-裁剪頭像</title>
<script src="!js/jquery-1.4.1.min.js" type="text/javascript"></script>
<script src="!js/cutpic.js" type="text/javascript"></script>
<script src="!js/uploadify-v2.1.4/jquery.uploadify.v2.1.4.min.js" type="text/javascript"></script>
<script src="!js/uploadify-v2.1.4/swfobject.js" type="text/javascript"></script>
<link href="!css/Main.css" rel="stylesheet" type="text/css"/>
<link href="!css/uploadify.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript">
var imageWidth =300;
var imageHeiht =300;
$(function(){
$('#uploadify').uploadify({
'uploader': '/!js/uploadify-v2.1.4/uploadify.swf',
'script': '/Handler/UploadAvatarHandler.ashx',
'cancelImg': '/!js/uploadify-v2.1.4/cancel.png',
'folder' : '/Temp',
'queueID': 'fileQueue',
'auto': true,
'multi': false,
'method' : 'get',
'fileExt': '*.jpg;*.png',
'fileDesc': '請選擇jpg , png文件...',
'scriptData': null,
'sizeLimit' : 2097152,
'onComplete': function (event, queueID, fileObj, response, data) {
if (response.indexOf('Temp') !=-1) {
$("#bgDiv img").remove(); //移除截圖區里image標簽
$("#btnSave").show(); //保存按鈕顯示
var result = response.split('$'); //得返回參數
var maxVal =0;
if(result[1] > result[2])
{
maxVal = result[2];
}
else
{
maxVal = result[1];
}
$("#maxVal").val(maxVal); //設置截圖區大小
$("#hidImageUrl").val(result[0]); //上傳路徑存入隱藏域
ShowImg(result[0],result[1],result[2]); //在截圖區顯示
$("#uploadify").uploadifySettings('scriptData',{'LastImgUrl':$('#hidImageUrl').val()}); //更新參數
}
else {
alert(response);
}
}
});
$("#btnSave").click(function(){
$.ajax({
type: "POST",
url: "/Handler/CutAvatarHandler.ashx",
data: {imgUrl:$('#hidImageUrl').val(),pointX:$("#x").val(),pointY:$("#y").val(),maxVal:$("#maxVal").val()},
success: function(msg) {
if (msg.indexOf('User') !=-1) {
$("#imgCut").attr("src",msg);
}
else
{
alert("error");
}
},
error: function(xhr, msg, e) {
alert("error");
}
});
});
});
function ShowImg(imagePath,imgWidth,imgHeight) {
var imgPath = imagePath !=""? imagePath : "!images/ef_pic.jpg";
var ic =new ImgCropper("bgDiv", "dragDiv", imgPath, imgWidth, imgHeight, null);
}
//{ Right: "rRight", Left: "rLeft", Up: "rUp", Down: "rDown", RightDown: "rRightDown", LeftDown: "rLeftDown", RightUp: "rRightUp", LeftUp: "rLeftUp"}
</script>
</head>
<body>
<form id="form1" runat="server">
<div class="fl avatarbg">
<div class="avatarboxbar">
<div id="bgDiv">
<div id="dragDiv">
</div>
</div>
</div>
</div>
<div class="avatarthumb">
<asp:Image ID="imgCut" ImageUrl="/!images/blank_pic.jpg" runat="server"/>
</div>
<br />
<div class="uploadimg">
<div class="upload">
<div class="uploadswf">
<input type="file" name="uploadify" id="uploadify"/>
</div>
<br />
<p id="fileQueue">
</p>
</div>
</div>
<input id="btnSave" type="button" value="保存" style="display: none;"/>
<input id="x" runat="server" type="hidden" value="0"/>
<input id="y" runat="server" type="hidden" value="0"/>
<input id="hidImageUrl" type="hidden" value=""/>
<input id="maxVal" runat="server" type="hidden" value="100"/>
</form>
</body>
</html>
上傳圖片Hander代碼(UploadAvatarHandler.ashx)
View Code
<%@ WebHandler Language="C#" Class="CutAvatarHandler" %>
using System;
using System.Web;
using System.Web.Services;
using System.Web.SessionState;
public class CutAvatarHandler : IHttpHandler, IRequiresSessionState
{
[WebMethod(EnableSession = true)]
public void ProcessRequest(HttpContext context)
{
context.Response.ContentType = "text/plain";
context.Response.Charset = "utf-8";
System.IO.Stream stream = null;
System.Drawing.Image originalImg = null; //原圖
System.Drawing.Image thumbImg = null; //縮放圖
try
{
int minWidth = 100; //最小寬度
int minHeight = 100; //最小高度
int maxWidth = 300; //最大寬度
int maxHeight = 300; //最大高度
string resultTip = string.Empty; //返回信息
HttpPostedFile file = context.Request.Files["Filedata"]; //上傳文件
string uploadPath = HttpContext.Current.Server.MapPath(@context.Request["folder"]); //得到上傳路徑
string lastImgUrl = @context.Request.Params["LastImgUrl"];
if (!string.IsNullOrEmpty(lastImgUrl))
{
PubClass.FileDel(HttpContext.Current.Server.MapPath(lastImgUrl));
}
if (file != null)
{
if (!System.IO.Directory.Exists(uploadPath))
{
System.IO.Directory.CreateDirectory(uploadPath);
}
string ext = System.IO.Path.GetExtension(file.FileName).ToLower(); //上傳文件的后綴(小寫)
if (ext == ".jpg" || ext == ".png")
{
string flag = "ThumbNail" + DateTime.Now.ToFileTime() + ext;
string uploadFilePath = uploadPath + "\\" + flag; //縮放圖文件路徑
stream = file.InputStream;
originalImg = System.Drawing.Image.FromStream(stream);
if (originalImg.Width > minWidth && originalImg.Height > minHeight)
{
thumbImg = PubClass.GetThumbNailImage(originalImg, maxWidth, maxHeight); //按寬、高縮放
if (thumbImg.Width > minWidth && thumbImg.Height > minWidth)
{
thumbImg.Save(uploadFilePath);
resultTip = @context.Request["folder"] + "\\" + flag + "$" + thumbImg.Width + "$" + thumbImg.Height;
}
else
{
resultTip = "圖片比例不符合要求";
}
}
else
{
resultTip = "圖片尺寸必須大于" + minWidth + "*" + minHeight;
}
}
}
else
{
resultTip = "上傳文件為空";
}
context.Response.Write(resultTip);
}
catch (Exception)
{
throw;
}
finally
{
if (originalImg != null)
{
originalImg.Dispose();
}
if (stream != null)
{
stream.Close();
stream.Dispose();
}
if (thumbImg != null)
{
thumbImg.Dispose();
}
GC.Collect();
}
}
public bool IsReusable
{
get
{
return false;
}
}
}
切割圖片Hander代碼(CutAvatarHandler.ashx)
View Code
<%@ WebHandler Language="C#" Class="CutAvatarHandler" %>
using System;
using System.Web;
using System.Web.SessionState;
public class CutAvatarHandler : IHttpHandler, IRequiresSessionState
{
public void ProcessRequest(HttpContext context)
{
context.Response.ContentType = "text/plain";
context.Response.Charset = "utf-8";
System.Drawing.Bitmap bitmap = null; //按截圖區域生成Bitmap
System.Drawing.Image thumbImg = null; //被截圖
System.Drawing.Graphics gps = null; //存繪圖對象
System.Drawing.Image finalImg = null; //最終圖片
try
{
string pointX = context.Request.Params["pointX"]; //X坐標
string pointY = context.Request.Params["pointY"]; //Y坐標
string imgUrl = context.Request.Params["imgUrl"]; //被截圖圖片地址
string rlSize = context.Request.Params["maxVal"]; //截圖矩形的大小
int finalWidth = 100;
int finalHeight = 100;
if (!string.IsNullOrEmpty(pointX) && !string.IsNullOrEmpty(pointY) && !string.IsNullOrEmpty(imgUrl))
{
string ext = System.IO.Path.GetExtension(imgUrl).ToLower(); //上傳文件的后綴(小寫)
bitmap = new System.Drawing.Bitmap(Convert.ToInt32(rlSize), Convert.ToInt32(rlSize));
thumbImg = System.Drawing.Image.FromFile(HttpContext.Current.Server.MapPath(imgUrl));
System.Drawing.Rectangle rl = new System.Drawing.Rectangle(Convert.ToInt32(pointX), Convert.ToInt32(pointY), Convert.ToInt32(rlSize), Convert.ToInt32(rlSize)); //得到截圖矩形
gps = System.Drawing.Graphics.FromImage(bitmap); //讀到繪圖對象
gps.DrawImage(thumbImg, 0, 0, rl, System.Drawing.GraphicsUnit.Pixel);
finalImg = PubClass.GetThumbNailImage(bitmap, finalWidth, finalHeight);
string finalPath = "/User/final" + DateTime.Now.ToFileTime() + ext;
finalImg.Save(HttpContext.Current.Server.MapPath(finalPath));
bitmap.Dispose();
thumbImg.Dispose();
gps.Dispose();
finalImg.Dispose();
GC.Collect();
PubClass.FileDel(HttpContext.Current.Server.MapPath(imgUrl));
context.Response.Write(finalPath);
}
}
catch (Exception)
{
throw;
}
}
public bool IsReusable
{
get
{
return false;
}
}
}
這種就可以達到我文章開頭的要求了
| 第三步:修復文件開頭提到Uploadify用Session在Chrome和FireFox下的Bug (身份驗證也一樣有這個BUG,修復同理) |
如果UploadAvatarHandler.ashx中要用到Session那就需求些額外的配置
在Global.asax中Application_BeginRequest加入下列代碼
protected void Application_BeginRequest(object sender, EventArgs e)
{
//為了Uploadify在谷歌和火狐下不能上傳的BUG
try
{
string session_param_name = "ASPSESSID";
string session_cookie_name = "ASP.NET_SessionId";
if (HttpContext.Current.Request.Form[session_param_name] != null)
{
UpdateCookie(session_cookie_name, HttpContext.Current.Request.Form[session_param_name]);
}
else if (HttpContext.Current.Request.QueryString[session_param_name] != null)
{
UpdateCookie(session_cookie_name, HttpContext.Current.Request.QueryString[session_param_name]);
}
}
catch
{
}
//此處是身份驗證
try
{
string auth_param_name = "AUTHID";
string auth_cookie_name = FormsAuthentication.FormsCookieName;
if (HttpContext.Current.Request.Form[auth_param_name] != null)
{
UpdateCookie(auth_cookie_name, HttpContext.Current.Request.Form[auth_param_name]);
}
else if (HttpContext.Current.Request.QueryString[auth_param_name] != null)
{
UpdateCookie(auth_cookie_name, HttpContext.Current.Request.QueryString[auth_param_name]);
}
}
catch { }
}
頁面中加入隱藏域
<asp:HiddenField ID="hdSessionId" runat="server" />
并在頁面的Load事件中,把SessionID賦給隱藏域
Uploadify()方法scriptData屬性在做修改
$('#uploadify').uploadify({
//....
'scriptData': { 'ASPSESSID': $('[id$=hdSessionId]').val() },
//.....
});
以上操作,用于修改身份驗證也一樣。。。
| 第四步:一些擴展 |
CutPic.js中有一些可以擴展
比如:有人要求截圖區域自己要可以拖動

把CutPic.js圖片顯示,截圖區HTML變成這樣
<div id="bgDiv">
<div id="dragDiv">
<div id="rRightDown" style="right: 0; bottom: 0;">
</div>
<div id="rLeftDown" style="left: 0; bottom: 0;">
</div>
<div id="rRightUp" style="right: 0; top: 0;">
</div>
<div id="rLeftUp" style="left: 0; top: 0;">
</div>
<div id="rRight" style="right: 0; top: 50%;">
</div>
<div id="rLeft" style="left: 0; top: 50%;">
</div>
<div id="rUp" style="top: 0; left: 50%;">
</div>
<div id="rDown" style="bottom: 0; left: 50%;">
</div>
</div>
</div>
再給這些新添DIV寫些樣式。。。^_^! 這里自己擴展吧
顯示區的JS加上最后一個參數
function ShowImg(imagePath,imgWidth,imgHeight) {
var imgPath = imagePath != "" ? imagePath : "!images/ef_pic.jpg";
var ic = new ImgCropper("bgDiv", "dragDiv", imgPath, imgWidth, imgHeight, { Right: "rRight", Left: "rLeft", Up: "rUp", Down: "rDown", RightDown: "rRightDown", LeftDown: "rLeftDown", RightUp: "rRightUp", LeftUp: "rLeftUp"});
}
可能還有需求上傳不要進度條,這個我沒找到屬性,有用過的可以指點一下,
不過這個問題沒有屬性也不是不可以解決的,可以在uploadify的JS文件中刪除或注釋掉append的這一段進度條HTML代碼。
這樣就做完了,Uploadify和這個CutPic.js幾乎能做到所有現在能看到的上傳截圖功能,還有的自己擴展一下^-^!
PS:示例代碼沒有優化,請各位自己做做優化^_^!
Demo下載:VS08: https://files.cnblogs.com/zhongweiv/CutAvatarVS08.rar
VS10: https://files.cnblogs.com/zhongweiv/CutAvatarVS10.rar
(大家在看這個Demo時好像遇到不少問題,我幫大家轉好了08和10的,各位可以下載,IIS的配置還是那樣)
Demo友情提示:布署在IIS上,再看,因為示例路徑全是從根目錄開始
| 對于各位看官的疑問解答: |
-----------------------------------------------------------------------------------------------------------------------------------
1.Demo相關(因為個人習慣,寫東西喜歡布暑在IIS中,路徑從根目錄開始,所以直接看,帶來了些不便^_^!)
如果沒有顯示出FLash上傳的,那一定是路徑有問題
對于Demo再加些操作提示,可能很多人沒有用過自定義端服務器:
1.布暑在IIS里,設置好端口號,如果是4.0環境,應用程序連接池選擇framework4.0
2.在VS中設置,選中網站項目,右鍵---->屬性頁---->啟動選項---->選擇自定義服務器---->基URL填入你在IIS里設置的,比如:http://localhost:XXXX/ (XXXX代表你在IIS里設置的端口號)
3.確實,運行頁面
如果用VS10轉化,在IIS里布暑點擊保存出來error
那有兩種可能
1.連接池framework的版本你還是沒選對
2,ISAPI和GCI限制里asp.net4.0沒有設置為允許。。。
如果這個Demo會出錯。。那你轉成4.0之后編譯應該就會報targetFramework的錯。。。。如果實在沒有什么IIS的設置經驗,建議自己搜索一下或者看看IIS方面的文章
-----------------------------------------------------------------------------------------------------------------------------------
2.onComplete事件方法中幾個參數的解釋:
event:名字就很明顯了
queueId 就是個唯一標識
fileObj 這是指那個文件
比如:fileObj.name 就是文件名
fileObj.size 是文件大小
上傳文件的相關信息都可以用這個獲得,還有創建時間,文件類型 等
response:這是你返回的信息
data:有四個屬性
filesUploaded :上傳了多少個文件
errors :出現了多少個錯誤
allBytesLoaded :總共上傳文件的大小(因為它可以多文件上傳)
speed :這是上傳速度
作 者:
Porschev[鐘慰]
出 處:
http://www.rzrgm.cn/zhongweiv/
微 博:
http://weibo.com/porschev
歡迎任何形式的轉載,但請務必注明原文詳細鏈接

浙公網安備 33010602011771號