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>&copy; @DateTime.Now.Year - Wu</p>        </footer>    </div>    @Scripts.Render("~/bundles/jcrop")        @RenderSection("scripts", required: false)</body></html>

运行结果如图:

这里写图片描述


这里写图片描述


这里写图片描述


这里写图片描述

阅读全文
1 0
原创粉丝点击