• ASP.NET MVC在服务端把异步上传的图片裁剪成不同尺寸分别保存,并设置上传目录的尺寸限制



    我曾经试过使用JSAjaxFileUploader插件来把文件、照片以异步的方式上传,就像"MVC文件图片ajax上传轻量级解决方案,使用客户端JSAjaxFileUploader插件01-单文件上传"中说的,这种方法足够轻、足够好。但今天,要在前面的基础上再增加2个需求:

     

    1、异步判断上传的图片是否超过最大限制
    2、把上传的图片裁剪成大中小3张图片,分别保存,删除的时候一块被删除

     

    上传图片如果超出最大尺寸限制,终止上传,并报错误信息。
    7

     

    前台上传图片,显示缩略图。
    3

     

    在项目根目录下的指定文件夹AjaxUpload中同时有了大中小3张图片。
    4

     

    点击图片行的删除按钮或重新上传新的图片,原先的大中小3张图片一块被删除。重新上传新图片:
    5

     

    在项目根目录下的指定文件夹AjaxUpload中同时有了新的大中小3张图片。
    6


    前端还是使用JSAjaxFileUploader插件,后端使用ImageResizer组件实现对图片的裁剪和保存。

     

    当前端拿到异步请求的返回结果后,需要显示图片、记录下图片的名称、错误信息等,可以把这些信息封装到UploadFileResult类中,让服务端以json格式返回。

    namespace MvcApplication1.Models
    
    {
    
        public class UploadFileResult
    
        {
    
            public string LargeFileName { get; set; } //带后缀名的图片名称,比如:20141112_large.jpg
    
            public string MediumFileName { get; set; }
    
            public string SmallFileName { get; set; } 
    
            public int Length { get; set; } //图片的字节数
    
            public string Type { get; set; } //图片的类型:image/jpeg
    
            public bool IsValid { get; set; } //用来判断是否超过尺寸最大限制
    
            public string Message { get; set; }
    
            public string LargeFilePath { get; set; }  //图片的保存路径:~/AjaxUpload/20141112_large.jpg
    
            public string MediumFilePath { get; set; }
    
            public string SmallFilePath { get; set; }  
    
        }
    
    }

    以上,
    LargeFileName用来保存裁剪大图的名称,类似"20141112_large.jpg",当前台需要删除图片的时候,还需要把这个图片名称传递给服务端,再到指定文件夹删除图片。
    LargeFilePath用来保存图片的路径,类似"~/AjaxUpload/20141112_large.jpg",前台显示图片的时候需要这个。
    IsValid为true表示可以裁剪保存图片,为false表示超过最大的尺寸限制,取消上传

     

    通过NuGet安装ImageResizer。安装完后,在"引用"下面多了一个ImageResizer组件。
    1

     

    创建HomeController,主要完成以下工作:
    1、接收前台上传图片,裁剪成大中小图片并分别保存
    2、接收前台需要删除的图片名称,在指定文件夹中同时删除大中小图片
    3、提供递归统计指定文件夹大小的方法
    ......

    using System;
    
    using System.Collections.Generic;
    
    using System.IO;
    
    using System.Web;
    
    using System.Web.Mvc;
    
    using ImageResizer;
    
    using MvcApplication1.Models;
    
    namespace MvcApplication1.Controllers
    
    {
    
        public class HomeController : Controller
    
        {
    
            public ActionResult Index()
    
            {
    
                return View();
    
            }
    
            [HttpPost]
    
            public ActionResult UploadFile()
    
            {
    
                //需要返回给前台的结果
    
                List<UploadFileResult> results = new List<UploadFileResult>();
    
                //遍历从前台传递而来的文件
    
                foreach (string file in Request.Files)
    
                {
    
                    //把每一个上传文件封装成HttpPostedFileBase
    
                    HttpPostedFileBase hpf = Request.Files[file] as HttpPostedFileBase;
    
                    //如果前台传来的文件集合中有null,继续遍历其他文件
    
                    if (hpf.ContentLength == 0 || hpf == null)
    
                    {
    
                        continue;
    
                    }
    
                    //给上传文件改名
    
                    string date = DateTime.Now.ToString("yyyyMMddhhmmss");
    
                    //目标文件夹的相对路径 ImageSize需要的格式
    
                    string pathForSaving = Server.MapPath("~/AjaxUpload/");
    
                    //目标文件夹的相对路径 统计文件夹大小需要的格式
    
                    string pathForSaving1 = Server.MapPath("~/AjaxUpload");
    
                    //保存文件并返回结果
    
                    if (this.CreateFolderIfNeeded(pathForSaving))
    
                    {
    
                        long currentSize = GetDirectoryLength(pathForSaving1);
    
                        //如果大于最大限制,直接返回json信息
    
                        //1M=1024*1024个字节
    
                        if (currentSize + hpf.ContentLength > 50 * 1024 * 1024)//最大允许50兆
    
                        {
    
                            results.Add(new UploadFileResult()
    
                            {
    
                                LargeFileName = "",
    
                                LargeFilePath = "",
    
                                MediumFileName = "",
    
                                MediumFilePath = "",
    
                                SmallFileName = "",
    
                                SmallFilePath = "",
    
                                IsValid = false,
    
                                Length = hpf.ContentLength,
    
                                Message = "超过最大限制无法上传",
    
                                Type = hpf.ContentType
    
                            });
    
                        }
    
                        else //如果小于最大限制,才保存大中小图片
    
                        {
    
                            //保存图片的各种版本:小图,中图,大图
    
                            var versions = new Dictionary<string, string>();
    
                            versions.Add("_small", "maxwidth=50&maxheight=50&format=jpg");
    
                            versions.Add("_medium", "maxwidth=200&maxheight=200&format=jpg");
    
                            versions.Add("_large", "maxwidth=600&maxheight=600&format=jpg");
    
                            //保存各个版本的缩略图
    
                            foreach (var key in versions.Keys)
    
                            {
    
                                hpf.InputStream.Seek(0, SeekOrigin.Begin);
    
                                ImageBuilder.Current.Build(new ImageJob(
    
                                    hpf.InputStream,
    
                                    pathForSaving + date + key, //不带后缀名的图片名称
    
                                    new Instructions(versions[key]),
    
                                    false,//是否保留原图
    
                                    true));//是否增加后缀
    
                            }
    
                            results.Add(new UploadFileResult()
    
                            {
    
                                LargeFileName = date + "_large" + ".jpg",
    
                                LargeFilePath = Url.Content(String.Format("~/AjaxUpload/{0}", date + "_large" + ".jpg")),
    
                                MediumFileName = date + "_medium" + ".jpg",
    
                                MediumFilePath = Url.Content(String.Format("~/AjaxUpload/{0}", date + "_mediume" + ".jpg")),
    
                                SmallFileName = date + "_small" + ".jpg",
    
                                SmallFilePath = Url.Content(String.Format("~/AjaxUpload/{0}", date + "_small" + ".jpg")),
    
                                IsValid = true,
    
                                Length = hpf.ContentLength,
    
                                Message = "上传成功",
    
                                Type = hpf.ContentType
    
                            });
    
                        }
    
                        
    
                    }
    
                }
    
                //单文件上传,实际上results中只有一个元素
    
                return Json(new
    
                {
    
                    largename = results[0].LargeFileName,
    
                    largepath = results[0].LargeFilePath,
    
                    mediumname = results[0].MediumFileName,
    
                    mediumpath = results[0].MediumFilePath,
    
                    smallname = results[0].SmallFileName,
    
                    smallpath = results[0].SmallFilePath,
    
                    type = results[0].Type,
    
                    size = string.Format("{0} bytes", results[0].Length),                
    
                    msg = results[0].Message,
    
                    isvalid = results[0].IsValid
    
                });
    
            }
    
            //根据文件名称删除文件
    
            [HttpPost]
    
            public ActionResult DeleteFileByNames(string largename, string mediumname, string smallname) 
    
            {
    
                string pathForSaving = Server.MapPath("~/AjaxUpload");
    
                System.IO.File.Delete(Path.Combine(pathForSaving, largename));
    
                System.IO.File.Delete(Path.Combine(pathForSaving, mediumname));
    
                System.IO.File.Delete(Path.Combine(pathForSaving, smallname));
    
                return Json(new
    
                {
    
                    msg = true
    
                });
    
            }
    
            /// <summary>
    
            /// 根据目标文件夹的相对路径创建文件夹
    
            /// 如果目标文件夹不存在,就创建;存在就不创建
    
            /// 只有在创建目标文件夹发生异常的时候才返回false
    
            /// </summary>
    
            /// <param name="path">目标文件夹的相对路径</param>
    
            /// <returns></returns>
    
            private bool CreateFolderIfNeeded(string path)
    
            {
    
                bool result = true;
    
                if (!Directory.Exists(path))
    
                {
    
                    try
    
                    {
    
                        Directory.CreateDirectory(path);
    
                    }
    
                    catch (Exception)
    
                    {
    
                        result = false;
    
                    }
    
                }
    
                return result;
    
            }
    
            /// <summary>
    
            /// 根据目标文件夹的相对路径递归计算该文件夹的大小
    
            /// </summary>
    
            /// <param name="path">用相对路径表示的目标文件夹</param>
    
            /// <returns></returns>
    
            private static long GetDirectoryLength(string path)
    
            {
    
                //如果目标文件夹不存在就返回0
    
                if (!Directory.Exists(path))
    
                {
    
                    return 0;
    
                }
    
                long size = 0;
    
                //获取目标文件夹的信息
    
                DirectoryInfo di = new DirectoryInfo(path);
    
                //遍历目标文件夹下的所有文件遍历累计每个文件的大小
    
                foreach (FileInfo fi in di.GetFiles())
    
                {
    
                    size += fi.Length;
    
                }
    
                //获取目标文件夹下的所有子文件夹
    
                DirectoryInfo[] dis = di.GetDirectories();
    
                //如果确实有子文件夹
    
                if (dis.Length > 0)
    
                {
    
                    //遍历这些子文件夹
    
                    for (int i = 0; i < dis.Length; i++)
    
                    {
    
                        //递归统计累计大小
    
                        size += GetDirectoryLength(dis[i].FullName);
    
                    }
    
                }
    
                return size;
    
            }
    
        }
    
    }
    

    以上,
    UploadFile方法中,通过Request.Files拿到所有的上传图片,然后遍历这些图片,通过Request.Files[key]获取某个图片,把该图片转换成HttpPostedFileBase类型。在裁剪保存图片之前,使用GetDirectoryLength方法获取当前文件夹的尺寸,如果没有超过尺寸的最大限制,就使用ImageResizer把图片裁剪成大中小3张图片,并分别保存。

    DeleteFileByNames方法中,从前台接收大中小图片的名称,再到根目录下的指定文件夹AjaxUpload中删除大中小3张图片。

     

    _Layout.cshtml中引入相关css、js文件。JQuery.JSAjaxFileUploaderSingle.js文件已经做了汉化,详细参考这里

    <head>
    
        <meta charset="utf-8" />
    
        <meta name="viewport" content="width=device-width" />
    
        <title>@ViewBag.Title</title>
    
        @Styles.Render("~/Content/css")
    
        <link href="~/Content/JSAjaxFileUploader/JQuery.JSAjaxFileUploader.css" rel="stylesheet" />
    
        @Scripts.Render("~/bundles/modernizr")
    
        @Scripts.Render("~/bundles/jquery")
    
        <script src="~/JSAjaxFileUploader/JQuery.JSAjaxFileUploaderSingle.js"></script>
    
    </head>
    
    <body>
    
        @RenderBody()    
    
        @RenderSection("scripts", required: false)
    
    </body>

     

    创建Home/Index.cshtml视图,主要工作包括:
    1、处理图片上传,每次上传前需要把原先的3张图片删除,如果上传成功显示小图的缩略图,如果上传失败,给出错误提示。
    2、提供一个动态创建图片行表格的方法
    3、提供一个删除大中小图片的方法,向服务端发送3张图片的名称
    ......

     

    @{
    
        ViewBag.Title = "Index";
    
        Layout = "~/Views/Shared/_Layout.cshtml";
    
    }
    
    <style type="text/css">
    
        #tb table {
    
            border-collapse: collapse;
    
             600px;
    
        }
    
        #tb td {
    
            text-align: center;
    
            padding-top: 5px;
    
             25%;
    
        }
    
        #tb tr {
    
            background-color: #E3E3E3;
    
            line-height: 35px;
    
        }
    
        .limit {
    
            color: red;
    
        }
    
    </style>
    
    <div id="testId"></div>
    
    <div id="tb">
    
        <table id="tbl">
    
            <tbody>
    
            </tbody>
    
        </table>
    
    </div>
    
    <div>
    
        <span class="limit"></span>
    
    </div>
    
    @section scripts
    
    {
    
        <script type="text/javascript">
    
            $(function() {
    
                //隐藏显示图片的表格
    
                $('#tbl').hide();
    
                //图片上传
    
                $('#testId').JSAjaxFileUploader({
    
                    uploadUrl: '@Url.Action("UploadFile","Home")',
    
                    inputText: '选择上传文件',
    
                    //fileName: 'photo',
    
                    maxFileSize: 512000,    //Max 500 KB file 1kb=1024字节
    
                    allowExt: 'gif|jpg|jpeg|png',
    
                    zoomPreview: false,
    
                    zoomWidth: 360,
    
                    zoomHeight: 360,
    
                    beforesend: function (file) {//每次点击都要删除原先的
    
                        if ($('.largeImgName').text() != "" && $('.mediumImgName').text() != "" && $('.smallImgName').text() != "") {
    
                            deleteImg();
    
                            $('#tbl').hide();
    
                        }
    
                    },
    
                    success: function (data) {
    
                        if (!data.isvalid) { //如果尺寸超过最大限制
    
                            $('.limit').css("display", "block");
    
                            $('.limit').text(data.msg);
    
                            return;
    
                        } else {
    
                            $('.limit').css("display", "none");
    
                            createTableTr();
    
                            $('#tbl').show();
    
                            $('.showImg').attr("src", data.smallpath);//显示小图片
    
                            $('.largeImgName').text(data.largename); //显示大图的名称
    
                            $('.mediumImgName').text(data.mediumname); //显示中图的名称
    
                            $('.smallImgName').text(data.smallname); //显示小图的名称
    
                        }                   
    
                    },
    
                    error: function (data) {
    
                        alert(data.msg);
    
                    }
    
                });
    
                //点击删除链接删除刚上传图片
    
                $('#tbl').on("click", ".delImg", function () {
    
                    deleteImg();
    
                    //window.location.reload();
    
                });
    
            });
    
            //创建表格
    
            function createTableTr() {
    
                var table = $('#tbl');
    
                table.append("<tr><td><img class='showImg'/></td><td colspan='2'><span class='largeImgName'></span><br/><span class='mediumImgName'></span><br/><span class='smallImgName'></span></td><td><a class='delImg' href='javascript:void(0)'>删除</a></td></tr>");
    
            }
    
            //删除图片方法:点击删除链接或上传新图片删除原先图片用到
    
            function deleteImg() {
    
                $.ajax({
    
                    cache: false,
    
                    url: '@Url.Action("DeleteFileByNames", "Home")',
    
                    type: "POST",
    
                    data: { largename: $('.largeImgName').text(), mediumname: $('.mediumImgName').text(), smallname: $('.smallImgName').text() },
    
                    success: function (data) {
    
                        if (data.msg) {
    
                            //alert("图片删除成功");
    
                            $('.delImg').parent().parent().remove();
    
                        }
    
                    },
    
                    error: function (jqXhr, textStatus, errorThrown) {
    
                        alert("出错了 '" + jqXhr.status + "' (状态: '" + textStatus + "', 错误为: '" + errorThrown + "')");
    
                    }
    
                });
    
            }
    
        </script>
    
    }
    

  • 相关阅读:
    详解Oracle临时表的几种用法及意义
    Testing and Debugging Procedures using SQL Developer 3.1
    ORACLE 流复制
    ORA01017 invalid username/password; logon denied
    oracle数据类型
    使用Pls_Integer的好处
    js取得上传图片大小
    高效整洁CSS代码原则
    在线压缩js和css
    图片等比例缩放后裁切
  • 原文地址:https://www.cnblogs.com/darrenji/p/4094348.html
Copyright © 2020-2023  润新知