mvc 截取上传图片做头像,自动生成不同小尺寸缩略图
很多SNS网站,可以上传头像,微博也是一样,上传的头像经自由裁剪合适后,自动生成多种不同尺寸高质量清晰的,如大中小。
效果如下:(下载链接在最下面)
实现:
页面代码:
<p class="phototxt">选择你要上传的头像</p> <div class="upfile"> @using (Html.BeginForm("uploadHead", "ucenter", FormMethod.Post, new { ID = "user_head_form", enctype = "multipart/form-data" })){ <input type="file" name="head" class="filebtn" onchange="$('#user_head_upload_box').hide();$('#user_head_show_box').show();$('#user_head_form').submit();" /> <input type="button" class="upimgbtn" value="上传头像" /> } </div>
<div class="sysbtn"> @using (Html.BeginForm("saveHead", "ucenter", FormMethod.Post, new { ID = "user_head_param_form", enctype = "multipart/form-data" })) { @Html.HiddenFor(model => model.headFileName, new { id = "head_name" }) @Html.HiddenFor(model => model.x, new { id = "head_x" }) @Html.HiddenFor(model => model.y, new { id = "head_y" }) @Html.HiddenFor(model => model.width, new { id = "head_width" }) @Html.HiddenFor(model => model.height, new { id = "head_height" }) <input type="submit" class="btnyes" value="保存"> <input type="button" class="btnno" value="取消" onclick="cancelHead();"> } </div>
section Scripts { <script src="@Url.Content("~/Scripts/jquery-1.7.1.min.js")"></script> <script src="@Url.Content("~/Scripts/jquery.form.js")"></script> <script src="@Url.Content("~/Scripts/imgareaselect/jquery.imgareaselect.pack.js")"></script> <script src="@Url.Content("~/Scripts/head.js")"></script> <script src="@Url.Content("~/Scripts/popup.js")"></script> <script type="text/javascript"> $(document).ready(function () { $("#user_head_form").ajaxForm({ success: function (data) { $('#user_head_upload_box').show(); $('#user_head_show_box').hide(); if (data != undefined && data != null) { if (data.msg == 0) { showreward("<span class=\"g_error\">请上传图片!</span>"); } else if (data.msg == -1) { showreward("<span class=\"g_error\">文件格式不对!</span>"); } else if (data.msg == -2) { showreward("<span class=\"g_error\">上传图片不能超过10M!</span>"); } else if (data.msg == -3) { showreward("<span class=\"g_error\">出现异常,请稍后再试!!</span>"); } else { var path = "/avatar/temp/" + data.msg; $("#head_name").val(data.msg); UserHeadUtil.initialize(path); } } } }); $("#user_head_param_form").ajaxForm({ success: function (data) { if (data.msg == 0) { showreward("<span class=\"g_error\">网络出现异常,请稍后再试!</span>"); } else if (data.msg == -1) { showreward("<span class=\"g_error\">系统出现异常,请稍后再试!</span>"); } else { showreward("<span class=\"g_ok\">修改成功!</span>"); $("img#origin_user_head_75").attr("src", "/avatar/75/" + data); $("img#top_user_head_25").attr("src", "/avatar/25/" + data); $('img#user_head_origin').imgAreaSelect({ remove: true }); $("#user_head_show_box").hide(); $("#user_head_upload_box").show(); $("#user_head_origin").attr({ "src": "/Content/img/upload.png", "width": "100%", "height": "100%" }); } } }); }); </script> }
后台代码:
[HttpPost] public ActionResult uploadHead(HttpPostedFileBase head)//命名和上传控件name 一样 { try { if ((head == null)) { return Json(new { msg = 0 }); } else { var supportedTypes = new[] { "jpg", "jpeg", "png", "gif","bmp" }; var fileExt = System.IO.Path.GetExtension(head.FileName).Substring(1); if (!supportedTypes.Contains(fileExt)) { return Json(new { msg = -1 }); } if (head.ContentLength > 1024 * 1000 * 10) { return Json(new { msg = -2 }); } Random r = new Random(); var filename = DateTime.Now.ToString("yyyyMMddHHmmss") + r.Next(10000) + "." + fileExt; var filepath = Path.Combine(Server.MapPath("~/avatar/temp"), filename); head.SaveAs(filepath); return Json(new { msg = filename }); } } catch (Exception) { return Json(new { msg = -3 }); } } 注意:
ajaxForm 提交时 ContentType 去掉这些属性就可以了 裸奔才行 不设置 application/json 或者 text/html
[HttpPost] [ValidateInput(false)] public ActionResult saveHead() { UploadImageModel model = new UploadImageModel(); model.headFileName = Request.Form["headFileName"].ToString(); model.x = Convert.ToInt32(Request.Form["x"]); model.y = Convert.ToInt32(Request.Form["y"]); model.width = Convert.ToInt32(Request.Form["width"]); model.height = Convert.ToInt32(Request.Form["height"]); if ((model == null)) { return Json(new { msg = 0 }); } else { var filepath = Path.Combine(Server.MapPath("~/avatar/temp"), model.headFileName); string fileExt = Path.GetExtension(filepath); Random r = new Random(); var filename = DateTime.Now.ToString("yyyyMMddHHmmss") + r.Next(10000) + fileExt; var path180 = Path.Combine(Server.MapPath("~/avatar/180"), filename); var path75 = Path.Combine(Server.MapPath("~/avatar/75"), filename); var path50 = Path.Combine(Server.MapPath("~/avatar/50"), filename); var path25 = Path.Combine(Server.MapPath("~/avatar/25"), filename); cutAvatar(filepath, model.x, model.y, model.width, model.height, 75L, path180, 180); cutAvatar(filepath, model.x, model.y, model.width, model.height, 75L, path75, 75); cutAvatar(filepath, model.x, model.y, model.width, model.height, 75L, path50, 50); cutAvatar(filepath, model.x, model.y, model.width, model.height, 75L, path25, 25); return Json(new { msg = 1 }); } } /// <summary> /// 创建缩略图 /// </summary> public void cutAvatar(string imgSrc, int x, int y, int width, int height, long Quality, string SavePath, int t) { Image original = Image.FromFile(imgSrc); Bitmap img = new Bitmap(t, t, PixelFormat.Format24bppRgb); img.MakeTransparent(img.GetPixel(0, 0)); img.SetResolution(72, 72); using (Graphics gr = Graphics.FromImage(img)) { if (original.RawFormat.Equals(ImageFormat.Jpeg) || original.RawFormat.Equals(ImageFormat.Png)|| original.RawFormat.Equals(ImageFormat.Bmp)) { gr.Clear(Color.Transparent); } if (original.RawFormat.Equals(ImageFormat.Gif)) { gr.Clear(Color.White); } gr.InterpolationMode = InterpolationMode.HighQualityBicubic; gr.SmoothingMode = SmoothingMode.AntiAlias; gr.CompositingQuality = CompositingQuality.HighQuality; gr.PixelOffsetMode = PixelOffsetMode.HighQuality; gr.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit; using (var attribute = new System.Drawing.Imaging.ImageAttributes()) { attribute.SetWrapMode(WrapMode.TileFlipXY); gr.DrawImage(original, new Rectangle(0, 0, t, t), x, y, width, height, GraphicsUnit.Pixel, attribute); } } ImageCodecInfo myImageCodecInfo = GetEncoderInfo("image/jpeg"); if (original.RawFormat.Equals(ImageFormat.Jpeg)) { myImageCodecInfo = GetEncoderInfo("image/jpeg"); } else if (original.RawFormat.Equals(ImageFormat.Png)) { myImageCodecInfo = GetEncoderInfo("image/png"); } else if (original.RawFormat.Equals(ImageFormat.Gif)) { myImageCodecInfo = GetEncoderInfo("image/gif"); }else if (original.RawFormat.Equals(ImageFormat.Bmp)) { myImageCodecInfo = GetEncoderInfo("image/bmp"); } Encoder myEncoder = Encoder.Quality; EncoderParameters myEncoderParameters = new EncoderParameters(1); EncoderParameter myEncoderParameter = new EncoderParameter(myEncoder, Quality); myEncoderParameters.Param[0] = myEncoderParameter; img.Save(SavePath, myImageCodecInfo, myEncoderParameters); } //根据长宽自适应 按原图比例缩放 private static Size GetThumbnailSize(System.Drawing.Image original, int desiredWidth, int desiredHeight) { var widthScale = (double)desiredWidth / original.Width; var heightScale = (double)desiredHeight / original.Height; var scale = widthScale < heightScale ? widthScale : heightScale; return new Size { Width = (int)(scale * original.Width), Height = (int)(scale * original.Height) }; } private static ImageCodecInfo GetEncoderInfo(String mimeType) { int j; ImageCodecInfo[] encoders; encoders = ImageCodecInfo.GetImageEncoders(); for (j = 0; j < encoders.Length; ++j) { if (encoders[j].MimeType == mimeType) return encoders[j]; } return null; } }
前端脚本:
//原图/缩略图 的比例 >=1 var UserHeadUtil = { ratio: 1, view_H:300, view_W:300, initialize:function(path){ $("#user_head_origin").attr("src", path); $("#user_head_upload_box").hide(); $("#user_head_show_box").show(); $("#user_head_25").attr("src", path); $("#user_head_50").attr("src", path); $("#user_head_75").attr("src", path); $("#user_head_180").attr("src", path); var img = new Image(); img.src = path; if(img.width==0){ var obj = this; img.onload = function(){ obj.imgOperate(img); }; }else{ this.imgOperate(img); } }, imgOperate:function(img){ if(img){ this.resize('user_head_origin', img.width, img.height, 300, 300); var x=0,y=0,size=0; if(this.view_W > this.view_H ){ x = (this.view_W - this.view_H)/2; size = this.view_H; }else if(this.view_W < this.view_H){ y = (this.view_H - this.view_W)/2; size = this.view_W; }else{ size = this.view_W; } var obj = this; $('img#user_head_origin').imgAreaSelect({ aspectRatio:"1:1", handles: "corners", persistent:true, show:true, imageWidth: obj.view_W, imageHeight: obj.view_H, x1: x, y1: y, x2: x + size, y2: y + size, onSelectChange: function(img, selection){ obj.preview('user_head_25', obj.view_W, obj.view_H, selection.x1, selection.y1, selection.width, selection.height, 25, 25); obj.preview('user_head_50', obj.view_W, obj.view_H, selection.x1, selection.y1, selection.width, selection.height, 50, 50); obj.preview('user_head_75', obj.view_W, obj.view_H, selection.x1, selection.y1, selection.width, selection.height, 75, 75); obj.preview('user_head_180', obj.view_W, obj.view_H, selection.x1, selection.y1, selection.width, selection.height, 180, 180); obj.setCutParams(selection.x1, selection.y1, selection.width, selection.height); } }); this.preview('user_head_25', this.view_W, this.view_H, x, y, size, size, 25, 25); this.preview('user_head_50', this.view_W, this.view_H, x, y, size, size, 50, 50); this.preview('user_head_75', this.view_W, this.view_H, x, y, size, size, 75, 75); this.preview('user_head_180', this.view_W, this.view_H, x, y, size, size, 180, 180); this.setCutParams(x, y, size, size); } }, resize:function(id, width, height, limit_W, limit_H){ if(width>0 && height>0){ if(width/height >= limit_W/limit_H){ if(width > limit_W){ this.view_W = limit_W; this.view_H = (limit_W/width)*height; } }else{ if(height > limit_H){ this.view_H = limit_H; this.view_W = (limit_H/height)*width; } } $('#'+id).attr( { "width" : this.view_W, "height" : this.view_H }); this.ratio = width / this.view_W; } }, preview:function(id, width, height, x, y, cut_W, cut_H, show_W, show_H){ var scaleX = show_W / (cut_W * this.ratio || 1); var scaleY = show_H / (cut_H * this.ratio || 1); $('#'+id).css({ width: Math.round(scaleX * width * this.ratio) + 'px', height: Math.round(scaleY * height * this.ratio) + 'px', marginLeft: '-' + Math.round(scaleX * x * this.ratio) + 'px', marginTop: '-' + Math.round(scaleY * y * this.ratio) + 'px' }); }, setCutParams:function(x, y, width, height){ $('#head_x').val(Math.round(x * this.ratio)); $('#head_y').val(Math.round(y * this.ratio)); $('#head_width').val(Math.round(width * this.ratio)); $('#head_height').val(Math.round(height * this.ratio)); } }; function cancelHead(){ // window.location.reload(); $('img#user_head_origin').imgAreaSelect({ remove: true }); $("#user_head_show_box").hide(); $("#user_head_upload_box").show(); $("#user_head_origin").attr({ "src": "/Content/img/upload.png", "width" : "100%", "height" : "100%" }); var path = $("img#origin_user_head_75").attr("src"); var index = path.lastIndexOf("/"); if(index!=-1){ var name = path.substring(index+1); $("#user_head_25").attr("src", "/headphone/25/"+name).css({ width: 25 + 'px', height: 25 + 'px', marginLeft: 0, marginTop: 0 }); $("#user_head_50").attr("src", "/headphone/50/" + name).css({ width: 50 + 'px', height: 50 + 'px', marginLeft: 0, marginTop: 0 }); $("#user_head_75").attr("src", "/headphone/75/" + name).css({ width: 75 + 'px', height: 75 + 'px', marginLeft: 0, marginTop: 0 }); $("#user_head_180").attr("src", "/headphone/180/" + name).css({ width: 180 + 'px', height: 180 + 'px', marginLeft: 0, marginTop: 0 }); } }
下载地址:
CSDN: http://download.csdn.net/download/zengzhan/5109105
BAIDU share:http://pan.baidu.com/share/link?shareid=389586&uk=2735096069
更多关于多种文件上传,分类到这里 http://www.cnblogs.com/zengxiangzhan/category/269831.html
附加 update 2016-08-08
方案使用 Jcrop 2.0.x 更成熟
<script src="js/Jcrop/Jcrop.min.js"></script> <link href="js/Jcrop/Jcrop.min.css" rel="stylesheet" />
高级使用方法
var m, jcrop_api, r = 172 / 120; function addImgAreaSelect() { $('.upload-pic-content').on('cropmove cropend', function (e, s, c) { preview(s, c); }); $('#user_head_origin').Jcrop({ aspectRatio: r, minSize: [43, 30], boxWidth: 444, boxHeight: 320, setSelect: [0, 0, 0, 0] }, function () { jcrop_api = this; init_interface(); }); function init_interface() { //c_w 压缩图片宽 xscale 原图片/压缩图片 比 var i = jcrop_api.getContainerSize(); c_w = Math.round(i[0]), c_h = Math.round(i[1]), xscale = jcrop_api.opt.xscale, yscale = jcrop_api.opt.yscale, w = 0, h = 0, x = 0, y = 0, c_w >= Math.floor(c_h * r) ? (x = (c_w - c_h * r) * xscale / 2, h = c_h * yscale, w = Math.round(h * r)) : (y = (c_h - c_w / r) * yscale / 2, w = c_w * xscale, h = Math.round(w / r)); jcrop_api.setSelect([x, y, w, h]); } } function jcropDestroy() { jcrop_api && jcrop_api.destroy() } function preview(s, c) { if (!c.w || !c.h) return; var cw = (s.core.opt.xscale * s.core.container.width()); var ch = (s.core.opt.yscale * s.core.container.height()); var scaleX = 172 / c.w; var scaleY = 120 / c.h; $('#user_head_150').css({ width: Math.round(scaleX * cw), height: Math.round(scaleY * ch), marginLeft: -Math.round(scaleX * c.x), marginTop: -Math.round(scaleY * c.y) }); $('#head_x').val(c.x); $('#head_y').val(c.y); $('#head_width').val(c.w); $('#head_height').val(c.h); }
类似微博九宫图最大化居中按比例缩略图
int sourceWidth = OriginalImage.Width; int sourceHeight = OriginalImage.Height; int destWidth = 0; int destHeight = 0; int destX = 0; int destY = 0; double o_scale = (double)sourceWidth / (double)sourceHeight; double scale = (double)Width / (double)Height; if (o_scale >= scale) { //原图长宽比大于或者等于缩略图长宽比,则按照宽度优先 (长>高) destX = (int)Math.Ceiling((sourceWidth - sourceHeight * scale) / 2f); destWidth = (int)Math.Ceiling(sourceHeight * scale); destHeight = sourceHeight; } else { //原图长宽比小于缩略图长宽比,则按照高度优先 (长<=高) destY = (int)Math.Ceiling((sourceHeight - sourceWidth / scale) / 2f); destWidth = sourceWidth; destHeight = (int)Math.Ceiling(sourceWidth / scale); }
更新 2017-11-29:
Touch not binded on repeat initializations when dynamically generated
解决:
function jcropDestroy() { jcrop_api && jcrop_api.destroy(); $.Jcrop.component.DragState.prototype.touch = null; }
//修复 iPhone and/or Android 移动端 拍照 后 图片 横竖颠倒 /// <summary> /// Rotate the given bitmap according to Exif Orientation data /// </summary> /// <param name="img">source image</param> /// <param name="updateExifData">set it to TRUE to update image Exif data after rotation (default is TRUE)</param> /// <returns>The RotateFlipType value corresponding to the applied rotation. If no rotation occurred, RotateFlipType.RotateNoneFlipNone will be returned.</returns> public static RotateFlipType RotateImageByExifOrientationData(Image img, bool updateExifData = true) { int orientationId = 0x0112; var fType = RotateFlipType.RotateNoneFlipNone; if (img.PropertyIdList.Contains(orientationId)) { var pItem = img.GetPropertyItem(orientationId); fType = GetRotateFlipTypeByExifOrientationData(pItem.Value[0]); if (fType != RotateFlipType.RotateNoneFlipNone) { img.RotateFlip(fType); if (updateExifData) img.RemovePropertyItem(orientationId); // Remove Exif orientation tag } } return fType; } /// <summary> /// Return the proper System.Drawing.RotateFlipType according to given orientation EXIF metadata /// </summary> /// <param name="orientation">Exif "Orientation"</param> /// <returns>the corresponding System.Drawing.RotateFlipType enum value</returns> public static RotateFlipType GetRotateFlipTypeByExifOrientationData(int orientation) { switch (orientation) { case 1: default: return RotateFlipType.RotateNoneFlipNone; case 2: return RotateFlipType.RotateNoneFlipX; case 3: return RotateFlipType.Rotate180FlipNone; case 4: return RotateFlipType.Rotate180FlipX; case 5: return RotateFlipType.Rotate90FlipX; case 6: return RotateFlipType.Rotate90FlipNone; case 7: return RotateFlipType.Rotate270FlipX; case 8: return RotateFlipType.Rotate270FlipNone; } }
用法:
//修复 iPhone and/or Android 移动端 拍照 后 图片 横竖颠倒 RotateFlipType fType = RotateImageByExifOrientationData(img, true); if (fType != RotateFlipType.RotateNoneFlipNone) { Thumbnail.SaveImg(img, path_original, img.Width, img.Height, 100L); } else { Thumbnail.SaveImg(img, path_original, img.Width, img.Height, 100L); }