Asp.Net无刷新上传并裁剪头像

 

 

 

开发网站几乎都做过上传图片并截图,做个无刷新Asp.Net上传并截图示例

实现功能:

1.选择文件,自动上传并生成缩放图(上传带进度条),形成预览图

2.在预览区,实现鼠标拖拽截图区,截取图片(示例截图区按缩放图小边为截图正方形长度,可扩展为截图区可变形式)

3.点击保存,截取小图,保存截取图并显示在页面上,并删除原缩略图

示例截图:

上传中

上传成功并截图

 

-------------------------------------------------------------------------------风骚分隔线-----------------------------------------------------------------------------------------------

 

第一步:准备工作,认识一些必要的东西 

 1.无刷新上传借助于Uploadify这个基于Flash的支持多文件上传的Jquery插件,很多人估计都用过了,我也在不同的项目中用过很多次,简单易用且功能强大

    (美中不足,插件本身对session使用有一点BUG,不过能解决,chrome&FireFox里上传如果代码中有用Session,获取不到)

 

没用过这个插件的可以去它的官网认识一下这个插件

Uploadify官网:  

  http://www.uploadify.com/

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:     http://files.cnblogs.com/zhongweiv/CutAvatarVS08.rar

                VS10:      http://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 :这是上传速度



 

 

 

 

 

posted @ 2011-11-29 13:42 porschev 阅读(...) 评论(...) 编辑 收藏

回到顶部