MVC4实现图片上传,裁剪和保存到服务器
来源:互联网 发布:牛头701在淘宝叫什么 编辑:程序博客网 时间:2024/06/08 13:13
PassPhotoController.cs
using System;using System.Collections.Generic;using System.Linq;using System.Web;using System.Web.Mvc;using PassPhotoMVC.Helpers;using System.Collections;namespace PhotoDemo.Controllers{ public class PassPhotoController : Controller { //初始化辅助类库和局部变量 PhotoUtils myUtils = new PhotoUtils(); //允许上传的最大文件大小 int maxSize = Convert.ToInt32(Settings.AppSettings.maxuploadsize); // all images are normalized to this height when uploaded //所有图像在上传时均标准化为此高度 //它们被放大或缩小 int hminRaw = Convert.ToInt32(Settings.AppSettings.uploadheight); //最终剪裁图像的所需尺寸(w,h) int hminCropped = Convert.ToInt32(Settings.AppSettings.passheight); int wminCropped = Convert.ToInt32(Settings.AppSettings.passwidth); int imgUploadPreview = Convert.ToInt32(Settings.AppSettings.uploadpreviewh); int prevw = Convert.ToInt32(Settings.AppSettings.previewwidth); int prevh = Convert.ToInt32(Settings.AppSettings.previewheight); /// <summary> /// 确定默认视图的参数 /// </summary> /// <param name="jsfilepath">只需要覆盖预设值</param> /// <returns></returns> public ActionResult Index(String jsFilePath="") { String RootPath = Request.Path; ViewBag.RootPath = RootPath; ViewBag.Height = prevh.ToString(); ViewBag.Width = prevw.ToString(); ViewBag.PreviewJSMarkup = myUtils.UpdatePreviewJs(prevw, prevh, jsFilePath); return View(); } /// <summary> ///如果最终用户尝试使用GET而不是POST调用此操作,则重定向以启动UI的界面 /// </summary> /// <returns></returns> [HttpGet] public ActionResult UploadImage() { return RedirectToAction("Index"); } /// <summary> /// 处理上传文件并将上传的文件大小调整为标准大小 /// </summary> /// <param name="mypostedfile"></param> /// <param name="targetfilename"></param> /// <param name="targetfolder"></param> /// <returns></returns> [HttpPost] public ActionResult UploadImage(HttpPostedFileBase myPostedFile, String targetFilename, String targetFolder = "raw", String srcimgfolder = "", String jsFilePath = "") { // This value is sent back to the view to accomodate relative URLs when in post action //在POST action时,此值将发回到视图以适应相关URL String rootPath = Request.Path.Replace("PassPhoto/UploadImage", ""); ViewBag.RootPath = rootPath; if (myPostedFile != null && myPostedFile.ContentLength > 0) { //img文件夹的默认值取自当前服务器上下文,除非在输入参数中另有说明 if (srcimgfolder == "") { srcimgfolder = Server.MapPath("~/uploaded_images/" + targetFolder + "/"); } else { if (!srcimgfolder.EndsWith("\\")) { srcimgfolder += "\\"; } srcimgfolder += targetFolder; } // preset name of file while testing refactor after tested //测试后重新测试的文件的预设名称 targetFilename = "image_upload_test.jpg"; ViewBag.Message = myUtils.UploadImage(myPostedFile, targetFilename, srcimgfolder, maxSize, hminRaw); if (ViewBag.Message == "OK: File uploaded!") { //返回修改UI必需的值 ViewBag.ImageName = targetFilename; ViewBag.ImageUrl = "uploaded_images/" + targetFolder + "/" + targetFilename; ViewBag.Height = imgUploadPreview.ToString(); ViewBag.Width = myUtils.CalculateResizedWidth(targetFilename, srcimgfolder, imgUploadPreview).ToString(); ViewBag.PreviewDisplay = "normal"; int jsWidth = myUtils.CalculateResizedWidth(targetFilename, srcimgfolder, hminRaw); ViewBag.PreviewJSMarkup = myUtils.UpdatePreviewJs(jsWidth, hminRaw, jsFilePath); } else { //返回默认值并显示操作结果的错误信息 ViewBag.ImageName = targetFilename; ViewBag.Height = prevh.ToString(); ViewBag.Width = prevw.ToString(); } } else { ViewBag.Message = "错误 - 文件无效 - 上传的文件为空."; } return View("Index"); } /// <summary> /// 如果最终用户尝试使用GET而不是POST调用此操作,则重定向以启动UI的界面。 /// </summary> /// <returns></returns> [HttpGet] public ActionResult CropImage() { return RedirectToAction("Index"); } /// <summary> /// 处理剪裁文件,保持纵横比和标准尺寸 /// </summary> /// <param name="filename"></param> /// <param name="folder"></param> /// <param name="X"></param> /// <param name="Y"></param> /// <param name="W"></param> /// <param name="H"></param> /// <returns></returns> [HttpPost] public ActionResult CropImage(String filename, String folder, String X, String Y, String W, String H, String srcimgfolder = "", String jsFilePath = "") { String rootPath = Request.Path.Replace("PassPhoto/CropImage", ""); ViewBag.RootPath = rootPath; String missingpar = ""; //validate required post parameters and return proper error message is something is missing //验证必需的post参数并返回缺少参数的合适的错误消息 if (filename == null ) { missingpar = "filename"; } if (folder == null) { if (missingpar != "") { missingpar += ", "; } missingpar = "folder"; } if (missingpar.Length >0) { String ermsg1 = "Error - missing parameter"; if (missingpar.Contains(",")) { ermsg1 += "s"; } ViewBag.Message = ermsg1 + ": " + missingpar; } else { // 将post的值转换为int int W1 = Convert.ToInt32(W); int H1 = Convert.ToInt32(H); int X1 = Convert.ToInt32(X); int Y1 = Convert.ToInt32(Y); //srcimagefolder的默认值将在运行时从服务器上下文确定 if (srcimgfolder == "") { srcimgfolder = Server.MapPath("~/uploaded_images/"); } else { if (!srcimgfolder.EndsWith("\\")) { srcimgfolder += "\\"; } } String targetfolder = "cropped"; ViewBag.Message = myUtils.CropImage(filename, folder, targetfolder, srcimgfolder, X1, Y1, W1, H1); if (ViewBag.Message == "OK - 文件裁剪完成了") { ViewBag.Height = imgUploadPreview.ToString(); ViewBag.Width = myUtils.CalculateResizedWidth(filename, srcimgfolder + targetfolder, imgUploadPreview).ToString(); ViewBag.ImageName = filename; ViewBag.PreviewDisplay = "normal"; ViewBag.ImageUrl = "uploaded_images/cropped/" + filename; ViewBag.PreviewJSMarkup = myUtils.UpdatePreviewJs(wminCropped, hminCropped, jsFilePath); } } return View("Index"); } }}
PhotoUtils.cs
using System;using System.Web;using System.IO;using System.Drawing;using System.Drawing.Imaging;namespace PhotoDemo.Helpers{ /// <summary> /// 处理上传图像的功能(调整大小/裁剪) /// </summary> /// public class PhotoUtils { /// <summary> /// Handle uploading of images, calls resizing for creating standard size images /// based on AppSettings parameters /// 处理图像的上传,根据AppSettings参数调用,调整大小以创建标准尺寸图像 /// </summary> /// <param name="postedfile"></param> /// <param name="targetfilename"></param> /// <param name="folder"></param> /// <param name="maxsize"></param> /// <param name="hmindimension"></param> /// <returns></returns> public String UploadImage(HttpPostedFileBase postedfile, String targetfilename, String folder, int maxsize = 262144, int hmindimension = 0) { String result = ""; // 如果hmindimension=0,则使用默认设置 if (hmindimension == 0) { hmindimension = Convert.ToInt32(Settings.AppSettings.uploadheight); } Boolean fileOK = false; int fileSize = postedfile.ContentLength; String maxk = ((int)((double)maxsize / 1024)).ToString(); if (fileSize > 0 & targetfilename.Length > 0) { String fileExtension = System.IO.Path.GetExtension(postedfile.FileName).ToLower(); String[] allowedExtensions = { ".jpg", ".jpeg" }; for (int i = 0; i <= allowedExtensions.Length - 1; i++) { if (allowedExtensions[i].Equals(fileExtension)) { fileOK = true; } } if (fileOK) { if (fileSize < maxsize) { try { result = ResizeImageUpload(postedfile.InputStream, targetfilename, folder, hmindimension); } catch(Exception ex) { result = "错误:无法上传文件<br>" + ex.Message; } } else { result = "错误:文件大于 " + maxk + "K.请上传较小的图像"; } } else { result = "错误:无法接受此类型的文件."; } } else { result = "错误:无法上传没有有效的目标文件名的照片."; } return result; } /// <summary> /// 处理上传图像的大小,使所有图像都缩放到标准高度 /// </summary> /// <param name="inputfilestream"></param> /// <param name="finalfilename"></param> /// <param name="folderpath"></param> /// <param name="hmindimension"></param> /// <returns></returns> public String ResizeImageUpload(Stream inputfilestream, String finalfilename, String folderpath, int hmindimension) { String result = ""; // 强制最终上传的图像以具有固定的高度 int newStillWidth, newStillHeight; int ori1; Image originalimg; try { originalimg = System.Drawing.Image.FromStream(inputfilestream); if (originalimg.Width > originalimg.Height) { //景观图片规则 ori1 = originalimg.Height; newStillHeight = hmindimension; newStillWidth = (int)((double)originalimg.Width * hmindimension / ori1); } else { //肖像图片规则 ori1 = originalimg.Width; newStillHeight = hmindimension; newStillWidth = (int)((double)newStillHeight * originalimg.Width / originalimg.Height); } Bitmap still = new Bitmap(newStillWidth, newStillHeight); Graphics gr_dest_still = Graphics.FromImage(still); SolidBrush sb = new SolidBrush(System.Drawing.Color.White); gr_dest_still.FillRectangle(sb, 0, 0, still.Width, still.Height); gr_dest_still.DrawImage(originalimg, 0, 0, still.Width, still.Height); try { ImageCodecInfo codecencoder = GetEncoder("image/jpeg"); int quality = 90; EncoderParameters encodeparams = new EncoderParameters(1); EncoderParameter qualityparam = new EncoderParameter(Encoder.Quality, quality); encodeparams.Param[0] = qualityparam; still.SetResolution(96, 96); if (!folderpath.EndsWith("\\")){ folderpath += "\\"; } still.Save(folderpath + finalfilename, codecencoder, encodeparams); result = "OK: File uploaded!"; } catch(Exception ex) { result = "ERROR: 保存图像时出现问题. " + ex.Message; } if (still!=null) { still.Dispose(); } } catch(Exception ex) { result = "ERROR: 这不是我们可以处理的图片. " + ex.Message; } return result; } /// <summary> /// 处理裁剪图像,将裁剪的图像缩放到AppSettings文件中配置的标准尺寸 /// </summary> /// <param name="filename"></param> /// <param name="sourcefolder"></param> /// <param name="targetfolder"></param> /// <param name="imgfolder"></param> /// <param name="X"></param> /// <param name="Y"></param> /// <param name="W"></param> /// <param name="H"></param> /// <returns></returns> public String CropImage(String filename, String sourcefolder, String targetfolder, String imgfolder, int X, int Y, int W, int H) { String result = ""; // 强制最终裁剪的图像以具有固定的尺寸 int croppedfinalw, croppedfinalh; croppedfinalh = Convert.ToInt32(Settings.AppSettings.passheight); croppedfinalw = Convert.ToInt32(Settings.AppSettings.passwidth); try { if (!imgfolder.EndsWith("\\")) { imgfolder += "\\"; } String sourcepath = imgfolder + sourcefolder + "\\"; Bitmap image1 = (Bitmap)Image.FromFile(sourcepath + filename, true); Rectangle rect = new Rectangle(X, Y, W, H); Bitmap cropped = image1.Clone(rect, image1.PixelFormat); // 释放原始图像,以防我们需要在下面覆盖它 if (image1 != null) { image1.Dispose(); } Bitmap finalcropped= new Bitmap(croppedfinalw, croppedfinalh); Graphics gr_finalcropped = Graphics.FromImage(finalcropped); SolidBrush sb = new SolidBrush(System.Drawing.Color.White); gr_finalcropped.FillRectangle(sb, 0, 0, finalcropped.Width, finalcropped.Height); gr_finalcropped.DrawImage(cropped, 0, 0, finalcropped.Width, finalcropped.Height); try { ImageCodecInfo codecencoder = GetEncoder("image/jpeg"); int quality = 92; EncoderParameters encodeparams = new EncoderParameters(1); EncoderParameter qualityparam = new EncoderParameter(Encoder.Quality, quality); encodeparams.Param[0] = qualityparam; finalcropped.SetResolution(240, 240); sourcepath = sourcepath.Replace(sourcefolder, targetfolder); finalcropped.Save(sourcepath + filename, codecencoder, encodeparams); result = "OK - 文件裁剪完成了"; } catch(Exception ex) { result = "ERROR: 保存图像时出现问题。 " + ex.Message; } if (cropped != null) { cropped.Dispose(); } if (finalcropped != null) { finalcropped.Dispose(); } } catch(Exception ex) { result = "ERROR: 这不是我们可以处理的图片. " + ex.Message; } return result; } public ImageCodecInfo GetEncoder(String mimetype) { ImageCodecInfo result = null; foreach (ImageCodecInfo codec in ImageCodecInfo.GetImageEncoders()) { if (codec.MimeType == mimetype){ result = codec; } } return result; } public int CalculateResizedWidth(String filename, String folderpath, int newh) { int result = 0; if (!folderpath.EndsWith("\\")) { folderpath += "\\"; } String fullpath = folderpath + filename; Bitmap image1 = (Bitmap)Image.FromFile(fullpath, true); if (image1 != null) { result = (int)((double)newh * image1.Width / image1.Height); image1.Dispose(); } return result; } /// <summary> /// Updates the javascript code sent to the view to handle the cropping /// based on the dimensions of the source image used for cropping. /// 更新发送到视图的JavaScript代码,以根据用于裁剪的源图像的尺寸来处理裁剪。 /// </summary> /// <param name="neww"></param> /// <param name="newh"></param> /// <param name="filepath"></param> /// <returns></returns> public String UpdatePreviewJs(int neww, int newh, String filepath="") { String result = ""; //读取默认的js源文件 //该结构允许通过在单元测试中传递测试文件路径进行单元测试 if (filepath == "" || filepath==null) { HttpContext ctx = HttpContext.Current; if (ctx != null) { filepath = ctx.Server.MapPath("~/js/tiffjcroppreset.js"); } } result = System.IO.File.ReadAllText(filepath); int startselect = result.IndexOf("width: Math.round"); int startvalue = result.IndexOf("(", startselect); int endvalue = result.IndexOf(")", startvalue); String selectvalue = result.Substring(startvalue, endvalue - startvalue + 1); String newvalue = "(rx*" + neww.ToString() + ")"; result = result.Replace(selectvalue, newvalue); //根据源图像改变高度 startselect = result.IndexOf("height: Math.round"); startvalue = result.IndexOf("(", startselect); endvalue = result.IndexOf(")", startvalue); selectvalue = result.Substring(startvalue, endvalue - startvalue + 1); newvalue = "(ry*" + newh.ToString() + ")"; result = result.Replace(selectvalue, newvalue); //配置前置宽高比 //从设置确定固定图像比例 String ratio = Settings.AppSettings.passwidth + "/" + Settings.AppSettings.passheight; startselect = result.IndexOf("aspectRatio:"); startvalue = result.IndexOf(" ", startselect); endvalue = result.IndexOf(",", startvalue); selectvalue = result.Substring(startvalue, endvalue - startvalue + 1); newvalue = " " + ratio + ","; result = result.Replace(selectvalue, newvalue); //配置rx的默认值 startselect = result.IndexOf("var rx"); startvalue = result.IndexOf("=", startselect); endvalue = result.IndexOf(";", startvalue); selectvalue = result.Substring(startvalue, endvalue - startvalue + 1); newvalue = "= " + Settings.AppSettings.previewwidth + " / c.w;"; result = result.Replace(selectvalue, newvalue); // 配置ry的默认值 startselect = result.IndexOf("var ry "); startvalue = result.IndexOf("=", startselect); endvalue = result.IndexOf(";", startvalue); selectvalue = result.Substring(startvalue, endvalue - startvalue + 1); newvalue = "= " + Settings.AppSettings.previewheight + " / c.h;"; result = result.Replace(selectvalue, newvalue); //Configure Explicit Resizing //配置显式调整大小 startselect = result.IndexOf("trueSize:"); startvalue = result.IndexOf("[", startselect); endvalue = result.IndexOf("]", startvalue); selectvalue = result.Substring(startvalue, endvalue - startvalue + 1); newvalue = "[" + neww.ToString() + ", " + newh.ToString() + "]"; result = result.Replace(selectvalue, newvalue); return result; } } }
PassPhoto视图文件夹
Index.cshtml
@{ //从设置中读取已裁剪图像的默认值 // 缩小到一半 var prevw = Settings.AppSettings.previewwidth + "px"; var prevh = Settings.AppSettings.previewheight + "px"; //处理从控制器发回的值,以刷新UI ViewBag.Title = "照片上传 - MVC"; var Image1W = prevw; var Image1H = prevh; var Image1src = "uploaded_images/raw/invalid.jpg"; var Imagename = "invalid.jpg"; var croppedpreviewLiteral = ""; var previewsrc = "uploaded_images/raw/invalid.jpg"; var displaypreview = "none"; var message = ""; var defaultfolder = "raw"; var uploadaction = "PassPhoto/UploadImage"; var cropaction = "PassPhoto/CropImage"; //消息确定清除,否则在UI中显示错误消息 if (ViewBag.Message != null) { message = ViewBag.Message; if (message.StartsWith("OK")) { message = ""; } } if (ViewBag.Height != null) { Image1H = ViewBag.Height; } if (ViewBag.Width != null) { Image1W = ViewBag.Width; } if (ViewBag.ImageUrl != null) { Image1src = ViewBag.ImageUrl; previewsrc = ViewBag.ImageUrl; } if (ViewBag.ImageName != null) { Imagename = ViewBag.ImageName; } if (ViewBag.PreviewDisplay != null) { displaypreview = ViewBag.PreviewDisplay; if (displaypreview == "normal") { croppedpreviewLiteral = "预览图片:"; } } if (Image1src.ToLower().Contains("cropped")) { defaultfolder = "cropped"; } if (ViewBag.rootPath != null) { Image1src = ViewBag.RootPath + Image1src; previewsrc = ViewBag.RootPath + previewsrc; uploadaction = ViewBag.RootPath + uploadaction; cropaction = ViewBag.RootPath + cropaction; }}<div> <h3>概念证明 - 在线图像裁剪</h3> 使用下面的"浏览..."按钮选择图像,并在准备好后单击"上传图像"。 <br /> <span id="errorLiteral" style="font-size:14px; color:Red; font-weight:bold"> @message </span> <br /> <form action="@uploadaction" method="post" enctype="multipart/form-data"> <input id="fileupload" name="mypostedfile" type="file" /> <input type="submit" id="uploadfileButton" value="上传图片" /> </form> <br /> <br /> <table> <tr> <td style="width:400px;"> <div id="imagenameLiteral">@Imagename</div> <br /><br /> <div> <img id="Image1" width="@Image1W" height="@Image1H" src="@Image1src" /> <br /> </div> </td> <td style="width:400px;"> <div id="croppedpreviewLiteral">@croppedpreviewLiteral</div> <div style="width:@prevw;height:@prevh;overflow:hidden;background-color:#ffffff;display:@displaypreview"> <img id="preview" width="@prevw" height="@prevh" src="@previewsrc" /> </div> </td> </tr> </table> <form action="@cropaction" method="post" enctype="multipart/form-data"> <input id="X1value" name="X" type="hidden" /> <input id="Y1value" name="Y" type="hidden" /> <input id="X2value" name="X2" type="hidden" /> <input id="Y2value" name="Y2" type="hidden" /> <input id="Wvalue" name="W" type="hidden" /> <input id="Hvalue" name="H" type="hidden" /> <input id="filename" name="filename" value="@Imagename" type="hidden" /> <input id="folder" name="folder" value="@defaultfolder" type="hidden" /> <div id="cropinstructions" style="width:400px"> 移动或重新排列原始图像内的选择工具,直到预览选项显示了你想保留的图像。准备好后,点击裁剪按钮,您的选择将会永久保存 <br /><br /> <input type="submit" id="cropimageButton" value="裁剪图像" /> </div> </form></div>@section scripts{ <script lang="Javascript"> @Html.Raw(ViewBag.PreviewJSMarkup) </script>}
_Layout.cshtml
<!DOCTYPE html><html><head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>@ViewBag.Title - 我的ASP.NET应用程序</title> @Styles.Render("~/bundles/css") </head><body> <div class="container body-content"> @RenderBody() <hr /> <footer> <p>© @DateTime.Now.Year - Wu</p> </footer> </div> @Scripts.Render("~/bundles/jcrop") @RenderSection("scripts", required: false)</body></html>
运行结果如图:
阅读全文
1 0
- MVC4实现图片上传,裁剪和保存到服务器
- html5 本地裁剪图片上传到服务器
- html Jcrop+canvas实现前端裁剪图片,并上传到服务器
- JAVA上传文件图片到服务器保存
- Android开发:相册读取、拍照、图片裁剪和图片上传服务器等功能的实现
- Android拍照,选择图片,裁剪和上传服务器
- croppic + thinkphp 实现图片的上传和裁剪
- 上传图片到服务器的实现
- 原生jq实现图片上传到服务器
- Java实现FTP上传图片到服务器
- 图片裁剪保存到数据库中的方法
- Android上传图片和文字到服务器
- cropper本地预览 裁剪,上传到服务器
- Android裁剪头像上传到远程服务器
- SpringMVC 上传图片保存到服务器 同时更改图片名称保存至数据库
- SpringMVC 上传图片保存到服务器 同时更改图片名称保存至数据库
- ios-对图片进行裁剪得到一个新图片和保存到相册
- imgareaselect+java实现图片裁剪保存
- 「NOIP2017模拟赛07.31」倒水
- 一类排列组合计数问题
- tow weeks(4)
- Spring的概念及作用
- Oracle数据库学习笔记之游标
- MVC4实现图片上传,裁剪和保存到服务器
- poj 3176 动态规划
- 英语单词中后缀-ee和-er的区别
- 单例模式——c++实现线程安全的单例类
- Java恢复练习笔记
- Oracle数据库学习笔记之异常处理,存储过程
- T626code学习笔记之浅谈Java垃圾回收(GC)
- poj 3264 (summerIII O) j树状数组 ST表(区间最值查询)
- Retrofit使用详解