欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

基于WebImage的图片上传工具类

程序员文章站 2022-07-02 14:50:07
基于WebImage封装图片上传工具类,支持缩略图和水印及其简单的配置。 ......

支持缩略图和水印。

基于WebImage的图片上传工具类
using System;
using System.IO;
using System.Linq;
using System.Web;
using System.Web.Helpers;

namespace HZC.Util.Mvc
{
    public class MvcImageUploader
    {
        #region 字段
        private string[] _imageExts = new string[] { "jpg", "jpeg", "png", "gif", "bmp" };  // 允许上传的图片类型
        private string _basePath;
        private string _baseLocalPath;
        private int _fileLimitSize;
        #endregion

        #region 构造函数
        /// <summary>
        /// MVC图片上传工具
        /// </summary>
        public MvcImageUploader() : this(1024 * 1024 * 2, "/Upload/Pics")
        { }

        /// <summary>
        /// MVC图片上传工具
        /// </summary>
        /// <param name="fileLimitSize">图片最大限制</param>
        public MvcImageUploader(int fileLimitSize) : this(fileLimitSize, "/Upload/Pics")
        { }

        /// <summary>
        /// MVC图片上传工具
        /// </summary>
        /// <param name="fileLimitSize">图片最大限制,默认2M</param>
        /// <param name="basePath">图片上传路径,默认为 ~/Upload/Pics </param>
        public MvcImageUploader(int fileLimitSize, string basePath)
        {
            _basePath = basePath;
            _fileLimitSize = fileLimitSize;
            _baseLocalPath = GetServerPath(_basePath);
        }
        #endregion

        #region 上传
        public ImgUploadResult UploadImage(WebImage image, bool isThumb = true, bool isWater = false, 
            ThumbOption thumbOption = null, WaterOption waterOption = null)
        {
            if (image == null)
            {
                return new ImgUploadResult {
                    Code = ImgUploadResultCode.文件不存在,
                    Message = "请求中未检测到文件"
                };
            }
            else
            {
                try
                {
                    string extName = Path.GetExtension(image.FileName).ToLower();
                    int size = image.GetBytes().Length;
                    int width = image.Width;
                    int height = image.Height;

                    // 验证文件类型
                    if (!ValidFileSize(size))
                    {
                        return new ImgUploadResult
                        {
                            Code = ImgUploadResultCode.文件大小超出限制,
                            Message = "文件大小超出限制"
                        };
                    }

                    // 验证文件大小
                    if (!ValidExtName(extName))
                    {
                        return new ImgUploadResult
                        {
                            Code = ImgUploadResultCode.不受支持的文件类型,
                            Message = "不受支持的文件类型"
                        };
                    }

                    var result = new ImgUploadResult();

                    // 图片位置相关
                    var folderName = GetImageUploadFolder();                                // 图片文件夹名称
                    var newFileName = GetNewFileName(extName);                              // 随机生成的图片名称
                    var newFolderPath = Path.Combine(_baseLocalPath, folderName);           // 图片文件夹在服务器上的物理路径
                    var newFilePath = Path.Combine(newFolderPath, newFileName);             // 图片在服务器上保存的物理路径
                    var thumbFilePath = Path.Combine(_baseLocalPath,                        // 缩略图在服务器上保存的物理路径
                        folderName, "Thumbs", newFileName);

                    if (!Directory.Exists(newFolderPath))                                   // 校验|创建图片文件夹
                    {
                        Directory.CreateDirectory(newFolderPath);
                        Directory.CreateDirectory(Path.Combine(newFolderPath, "Thumbs"));
                    }

                    // 获取水印
                    if (isWater)
                    {
                        if (waterOption != null)
                        {
                            if (waterOption.Type == WaterType.图片)
                            {
                                // 图片水印
                                if (!string.IsNullOrWhiteSpace(waterOption.Content))
                                {
                                    var path = GetServerPath(waterOption.Content);
                                    if (File.Exists(path))
                                    {
                                        WebImage img = new WebImage(path);
                                        int w = waterOption.Width > 0 ? waterOption.Width : img.Width;
                                        // int h = waterOption.Height > 0 ? waterOption.Height : img.Height;
                                        var h = waterOption.Height;
                                        if (h == 0)
                                        {
                                            h = img.Height * w / img.Width;
                                        }

                                        image.AddImageWatermark(img, w, h, 
                                            waterOption.HorizontalPostion, waterOption.VerticalPostion, 
                                            waterOption.Opacity, waterOption.Padding);
                                    }                                    
                                }
                            }
                            else
                            {
                                // 文字水印
                                if (!string.IsNullOrWhiteSpace(waterOption.Content))
                                {

                                    image.AddTextWatermark(waterOption.Content, waterOption.FontColor, waterOption.FontSize, waterOption.FontStyle,
                                        waterOption.FontFamily, waterOption.HorizontalPostion, waterOption.VerticalPostion,
                                        waterOption.Opacity, waterOption.Padding);
                                }
                            }
                        }
                    }

                    image.Save(newFilePath);                                                 // 保存文件

                    result.Code = ImgUploadResultCode.上传成功;
                    result.Message = "";
                    result.ImageUrl = _basePath + "/" + folderName + "/" + newFileName;
                    result.ThumbUrl = "";
                    result.Size = size;
                    result.Width = width;
                    result.Height = height;
                    result.Ext = extName;

                    // 缩略图
                    if (isThumb)
                    {
                        var thumb = MakeThumb(image, thumbOption);
                        thumb.Save(thumbFilePath);
                        result.ThumbUrl = _basePath + "/" + folderName + "/Thumbs/" + newFileName;
                    }

                    return result;
                }
                catch (Exception ex)
                {
                    SimpleLog.WriteErrorLogAsyn("UploaderController.Image", ex.Message + ":" + ex.StackTrace);
                    return new ImgUploadResult
                    {
                        Code = ImgUploadResultCode.系统异常,
                        Message = ex.Message + ":" + ex.StackTrace,
                        Size = 0,
                        Ext = "",
                        ImageUrl = "",
                        ThumbUrl = "",
                        Width = 0,
                        Height = 0
                    };
                }
            }
        }
        #endregion

        #region 生成缩略图
        private WebImage MakeThumb(WebImage source, ThumbOption option = null)
        {
            if (option == null)
            {
                option = new ThumbOption();
            }

            WebImage thumb;
            if (option.IsCrop)
            {
                if (source.Width <= option.Width || source.Height <= option.Height)
                {
                    thumb = source.Resize(option.Width, option.Height, true, true);
                }
                else
                {
                    var wScale = source.Width / option.Width;
                    var hScale = source.Height / option.Height;
                    
                    var direct = 0;     // 0:横向;1:纵向

                    var thumbWidth = 0;
                    var thumbHeight = 0;

                    if (wScale >= hScale)
                    {
                        direct = 0;
                        thumbHeight = option.Height + 2;
                        thumbWidth = option.Height * source.Width / source.Height;
                    }
                    else
                    {
                        direct = 1;
                        thumbWidth = option.Width + 2;
                        thumbHeight = option.Width * source.Height / source.Width;
                    }

                    thumb = source.Resize(thumbWidth, thumbHeight, false, false);

                    if (direct == 0)
                    {
                        var py = (thumbWidth - option.Width) / 2;
                        thumb = thumb.Crop(1, py, 1, py);
                    }
                    else
                    {
                        var py = (thumbHeight - option.Height) / 2;
                        thumb = thumb.Crop(py, 1, py, 1);
                    }
                }
            }
            else
            {
                thumb = source.Resize(option.Width, option.Height, true, true);
            }
            return thumb;
        }
        #endregion

        #region 获取图片的上传文件夹
        private string GetImageUploadFolder()
        {
            string folderName = DateTime.Today.ToString("yyyyMM");
            return folderName;
        }
        #endregion

        #region 获取文件上传后的文件名称
        private string GetNewFileName(string ext)
        {
            string fileName = Path.GetRandomFileName();
            return fileName + "." + ext;
        }
        #endregion

        #region 验证文件扩展名
        private bool ValidExtName(string ext)
        {
            return _imageExts.Contains(ext);
        }
        #endregion

        #region 验证文件大小
        private bool ValidFileSize(int size)
        {
            return size <= _fileLimitSize;
        }
        #endregion

        #region 获取指定路径在服务器上的位置
        private string GetServerPath(string url)
        {
            url = url.ToLower();
            if (url.StartsWith("http://") || url.StartsWith("https://"))
            {
                return url;
            }
            else if (HttpContext.Current != null)
            {
                return HttpContext.Current.Server.MapPath(url);
            }
            else
            {
                return string.Empty;
            }
        }
        #endregion
    }

    /// <summary>
    /// 图片上传结果
    /// </summary>
    public class ImgUploadResult
    {
        /// <summary>
        /// 结果码
        /// </summary>
        public ImgUploadResultCode Code { get; set; }

        /// <summary>
        /// 消息
        /// </summary>
        public string Message { get; set; }

        /// <summary>
        /// 图片上传成功后的相对路径,如:/Upload/Pic/...
        /// </summary>
        public string ImageUrl { get; set; }

        /// <summary>
        /// 缩略图的相对路径
        /// </summary>
        public string ThumbUrl { get; set; }

        /// <summary>
        /// 图片的扩展名
        /// </summary>
        public string Ext { get; set; }

        /// <summary>
        /// 图片的大小
        /// </summary>
        public int Size { get; set; }

        /// <summary>
        /// 图片的宽度
        /// </summary>
        public int Width { get; set; }

        /// <summary>
        /// 图片的高度
        /// </summary>
        public int Height { get; set; }
    }

    /// <summary>
    /// 缩略图配置选项
    /// </summary>
    public class ThumbOption
    {
        /// <summary>
        /// 缩略图宽度
        /// </summary>
        public int Width { get; set; } = 180;

        /// <summary>
        /// 缩略图高度
        /// </summary>
        public int Height { get; set; } = 180;

        /// <summary>
        /// 是否保持图片的宽高比
        /// </summary>
        public bool IsPreserveAspectRatio { get; set; } = true;

        /// <summary>
        /// 是否阻止放大图片
        /// </summary>
        public bool IsPreventEnlarge { get; set; } = true;

        /// <summary>
        /// 是否裁剪图片,
        /// 如果裁剪,图片短边适应缩略图尺寸,自动缩放长边,并根据缩略图尺寸从中心裁剪长边
        /// 如果裁剪,图片长边适应缩略图尺寸,短边按比例缩放
        /// </summary>
        public bool IsCrop { get; set; } = false;
    }

    /// <summary>
    /// 水印配置选项
    /// </summary>
    public class WaterOption
    {
        /// <summary>
        /// 水印类型,图片|文字
        /// </summary>
        public WaterType Type { get; set; }

        /// <summary>
        /// 水印内容,
        /// 类型为图片时,传入水印图片相对根目录的路径,如:/Upload/Pics/201801/xxx.jpg
        /// 类型为文字时,传入水印的文字
        /// </summary>
        public string Content { get; set; }

        /// <summary>
        /// 水印的水平位置,
        /// 可选为 Left|Center|Right
        /// </summary>
        public string HorizontalPostion { get; set; } = "Right";

        /// <summary>
        /// 水印的垂直位置,
        /// 可选为 Top|Middle|Bottom
        /// </summary>
        public string VerticalPostion { get; set; } = "Bottom";

        /// <summary>
        /// 水印图片的宽度,仅当水印类型为图片时有效
        /// </summary>
        public int Width { get; set; } = 0;

        /// <summary>
        /// 水印图片的高度,仅当水印类型为图片时有效
        /// </summary>
        public int Height { get; set; } = 0;

        /// <summary>
        /// 水印的透明度,100为完全不透明,0为完全透明
        /// </summary>
        public int Opacity { get; set; } = 50;

        /// <summary>
        /// 边距大小
        /// </summary>
        public int Padding { get; set; } = 5;

        /// <summary>
        /// 水印文本的字体,仅当水印类型为文本时有效
        /// 注意,若指定字体在服务器上不存在,会抛出报错
        /// </summary>
        public string FontFamily { get; set; } = "Microsoft Sans Serif";

        /// <summary>
        /// 水印文本的样式,仅当水印类型为文本时有效
        /// 可选项目 Regular|Bold|Italic|Strikeout|Underline
        /// </summary>
        public string FontStyle { get; set; } = "Regular";

        /// <summary>
        /// 水印文本的文字大小,仅当水印类型为文本时有效
        /// </summary>
        public int FontSize { get; set; } = 12;

        /// <summary>
        /// 水印文本的文字颜色,仅当水印类型为文本时有效
        /// 赋值类似于 "White"、"Black" 或 "DarkBlue",或 "#RRGGBB" 或 "#RGB" 形式的十六进制值
        /// </summary>
        public string FontColor { get; set; } = "Black";
    }

    /// <summary>
    /// 图片上传结果码的枚举
    /// </summary>
    public enum ImgUploadResultCode
    {
        不受支持的文件类型 = 511,
        文件大小超出限制 = 512,
        文件不存在 = 514,
        系统异常 = 500,
        上传成功 = 200
    }

    /// <summary>
    /// 水印类型的枚举
    /// </summary>
    public enum WaterType
    {
        文字 = 1,
        图片 = 2
    }
}
View Code

 

上面是工具的代码,调用例子如下:

 1 [HttpPost]
 2         public JsonResult ImageUpload()
 3         {
 4             if (HttpContext.Request.RequestType == "GET")
 5             {
 6                 return Json(new ImgUploadResult { Code = ImgUploadResultCode.文件不存在 });
 7             }
 8 
 9             ImgUploadResult result;
10             WebImage image = WebImage.GetImageFromRequest("");
11             if (image == null)
12             {
13                 return Json(new ImgUploadResult { Code = ImgUploadResultCode.文件不存在 });
14             }
15 
16             MvcImageUploader uploader = new MvcImageUploader();
17 
18             // 文字水印
19             result = uploader.UploadImage(image, true, true,
20                 new ThumbOption { IsCrop = true },
21                 new WaterOption
22                 {
23                     Content = "这是文字水印",
24                     FontFamily = "微软雅黑",
25                     FontSize = 18,
26                     FontColor = "#FF0000",
27                     Padding = 30,
28                     HorizontalPostion = "Center",
29                     VerticalPostion = "Middle",
30                     Opacity = 80
31                 });
32 
33             // 图片水印
34             //result = uploader.UploadImage(image, true, true,
35             //    new ThumbOption { IsCrop = true },
36             //    new WaterOption
37             //    {
38             //        Type = WaterType.图片,
39             //        Content = "/Upload/Pics/201801/cctv1.jpg",
40             //        HorizontalPostion = "Center",
41             //        VerticalPostion = "Middle",
42             //        Width = 150
43             //    });
44             return Json(result);
45         }