[WebApi] 捣鼓一个资源管理器--服务器端分割压缩图片

《打造一个网站或者其他网络应用的文件管理接口(WebApi)第五章“服务器端分割压缩图片”》

========================================================

作者:qiujuer

博客:blog.csdn.net/qiujuer

网站:www.qiujuer.net

开源库:Genius-Android

转载请注明出处:http://blog.csdn.net/qiujuer/article/details/41826865

========================================================

History

[WebApi] 捣鼓一个资源管理器--数据库辅助服务器文件访问

In This

在做网站开发时,我常常会做一些这样的工作:一张大图中包含了许多的小图,而网站中为了使用其中一张小图我不得不把大图切成一张张的小图。虽然这样的工作不多;但对于我来说在服务器端莫名的存储了一大堆小文件是很反感的事情;或许你会说使用css来完成大图中的小图显示;当然这是可以的。但是我假如需要下载该小图呢?这时无能为力了吧!

所以有了今天的服务器端剪切压缩图片的一章。

CodeTime

更改

本次版本相对上一张主要两个地方更改:新增 ImageUtils.cs,修改 ResourceApiController.cs

ImageUtils.cs
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.IO;

namespace WebResource.Models
{
    public class ImageUtils
    {
        /// <summary>
        /// 图片类型对应的ImageFormat
        /// </summary>
        /// <param name="type">类型</param>
        /// <returns>ImageFormat</returns>
        public static ImageFormat GetFormat(string type)
        {
            Dictionary<string, ImageFormat> types = new Dictionary<string, ImageFormat>();
            types.Add("bmp", ImageFormat.Bmp);
            types.Add("gif", ImageFormat.Gif);
            types.Add("ief", ImageFormat.Jpeg);
            types.Add("jpeg", ImageFormat.Jpeg);
            types.Add("jpg", ImageFormat.Jpeg);
            types.Add("jpe", ImageFormat.Jpeg);
            types.Add("png", ImageFormat.Png);
            types.Add("tiff", ImageFormat.Tiff);
            types.Add("tif", ImageFormat.Tiff);
            types.Add("djvu", ImageFormat.Bmp);
            types.Add("djv", ImageFormat.Bmp);
            types.Add("wbmp", ImageFormat.Bmp);
            types.Add("ras", ImageFormat.Bmp);
            types.Add("pnm", ImageFormat.Bmp);
            types.Add("pbm", ImageFormat.Bmp);
            types.Add("pgm", ImageFormat.Bmp);
            types.Add("ppm", ImageFormat.Bmp);
            types.Add("rgb", ImageFormat.Bmp);
            types.Add("xbm", ImageFormat.Bmp);
            types.Add("xpm", ImageFormat.Bmp);
            types.Add("xwd", ImageFormat.Bmp);
            types.Add("ico", ImageFormat.Icon);
            types.Add("wmf", ImageFormat.Emf);
            types.Add("exif", ImageFormat.Exif);
            types.Add("emf", ImageFormat.Emf);

            try
            {
                ImageFormat format = types[type];
                if (format != null)
                    return format;
            }
            catch { }
            return ImageFormat.Bmp;
        }

        /// <summary>
        /// 图片转换为字节
        /// </summary>
        /// <param name="bitmap">图片</param>
        /// <param name="type">类型</param>
        /// <returns>字节码</returns>
        public static byte[] ToBytes(Bitmap bitmap, string type)
        {
            using (MemoryStream stream = new MemoryStream())
            {
                bitmap.Save(stream, GetFormat(type));
                byte[] data = new byte[stream.Length];
                stream.Seek(0, SeekOrigin.Begin);
                stream.Read(data, 0, Convert.ToInt32(stream.Length));
                return data;
            }
        }

        /// <summary>
        ///  调整图片宽度高度
        /// </summary>
        /// <param name="bmp">原始Bitmap </param>
        /// <param name="newW">新的宽度</param>
        /// <param name="newH">新的高度</param>
        /// <returns>处理Bitmap</returns>  

        public static Bitmap Resize(Bitmap bmp, int newW, int newH)
        {
            try
            {
                Bitmap b = new Bitmap(newW, newH);
                Graphics g = Graphics.FromImage(b);
                // 插值算法的质量
                g.InterpolationMode = InterpolationMode.Default;
                g.DrawImage(bmp, new Rectangle(0, 0, newW, newH), new Rectangle(0, 0, bmp.Width, bmp.Height), GraphicsUnit.Pixel);
                g.Dispose();
                return b;
            }
            catch
            {
                return null;
            }
        }

        /// <summary>
        /// 切片Bitmap:指定图片分割为 Row 行,Col 列,取第 N 个图片
        /// </summary>
        /// <param name="b">等待分割的图片</param>
        /// <param name="row">行</param>
        /// <param name="col">列</param>
        /// <param name="n">取第N个图片</param>
        /// <returns>切片后的Bitmap</returns>
        public static Bitmap Cut(Bitmap b, int row, int col, int n)
        {
            int w = b.Width / col;
            int h = b.Height / row;

            n = n > (col * row) ? col * row : n;

            int x = (n - 1) % col;
            int y = (n - 1) / col;

            x = w * x;
            y = h * y;

            try
            {
                Bitmap bmpOut = new Bitmap(w, h, PixelFormat.Format24bppRgb);
                Graphics g = Graphics.FromImage(bmpOut);
                g.DrawImage(b, new Rectangle(0, 0, w, h), new Rectangle(x, y, w, h), GraphicsUnit.Pixel);
                g.Dispose();
                return bmpOut;
            }
            catch
            {
                return null;
            }
        }
    }
}

该类的作用就是压缩和剪切图片,其具体实现也都注释清楚了;如果不明白的地方,还望在评论中提出。

然后来看看这次的API更改。

ResourceApiController.cs
        /// <summary>
        /// Get Image
        /// </summary>
        /// <param name="name">MD5 Name</param>
        /// <returns>File</returns>
        [HttpGet]
        [Route("{Id}/Img")]
        public async Task<HttpResponseMessage> GetImage(string Id, int w = 0, int h = 0, int r = 1, int c = 1, int n = 1)
        {
            // Return 304
            var tag = Request.Headers.IfNoneMatch.FirstOrDefault();
            if (Request.Headers.IfModifiedSince.HasValue && tag != null && tag.Tag.Length > 0)
                return new HttpResponseMessage(HttpStatusCode.NotModified);

            // 判断参数是否正确
            if (w < 0 || h < 0 || r < 1 || c < 1 || n < 1)
                return new HttpResponseMessage(HttpStatusCode.BadRequest);

            // 默认参数情况直接返回
            if (w == 0 && h == 0 && r == 1 && c == 1 && n == 1)
                return await Get(Id);

            // 查找数据库
            Resource model = await db.Resources.FindAsync(Id);

            // 判断
            if (model == null || !GetContentType(model.Type).StartsWith("image"))
                return new HttpResponseMessage(HttpStatusCode.BadRequest);

            // 加载文件信息
            FileInfo info = new FileInfo(Path.Combine(ROOT_PATH, model.Folder, model.Id));
            if (!info.Exists)
                return new HttpResponseMessage(HttpStatusCode.BadRequest);

            // 打开图片
            Bitmap bitmap = new Bitmap(info.FullName);

            // 剪切
            if (r > 1 || c > 1)
            {
                bitmap = ImageUtils.Cut(bitmap, r, c, n);
            }

            // 放大缩小
            if (w > 0 || h > 0)
            {
                w = w == 0 ? bitmap.Width : w;
                h = h == 0 ? bitmap.Height : h;

                bitmap = ImageUtils.Resize(bitmap, w, h);
            }

            try
            {
                // Copy To Memory And Close.
                byte[] bytes = ImageUtils.ToBytes(bitmap, model.Type);
                // Get Tag
                string eTag = string.Format("\"{0}\"", HashUtils.GetMD5Hash(bytes));

                // 构造返回
                HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK);

                ContentDispositionHeaderValue disposition = new ContentDispositionHeaderValue(GetDisposition(model.Type));
                disposition.FileName = string.Format("{0}.{1}", model.Name, model.Type);
                disposition.Name = model.Name;
                // 这里写入大小为计算后的大小
                disposition.Size = bytes.Length;

                result.Content = new ByteArrayContent(bytes);
                result.Content.Headers.ContentType = new MediaTypeHeaderValue(GetContentType(model.Type));
                result.Content.Headers.ContentDisposition = disposition;
                // Set Cache 这个同Get方法
                result.Content.Headers.Expires = new DateTimeOffset(DateTime.Now).AddHours(1);
                result.Content.Headers.LastModified = new DateTimeOffset(DateTime.Now);
                result.Headers.CacheControl = new CacheControlHeaderValue() { Public = true, MaxAge = TimeSpan.FromHours(1) };
                result.Headers.ETag = new EntityTagHeaderValue(eTag);
                return result;
            }
            catch { }
            finally
            {
                if (bitmap != null)
                    bitmap.Dispose();
            }

            return new HttpResponseMessage(HttpStatusCode.BadRequest);
        }

由于代码量较多,我就不全部贴出来了;就把更改的地方写出来了;其中主要就是新增了一个
GetImage 方法。

在方法中,根据传入的参数我们进行一定的判断然后剪切压缩图片;最后打包为 Http 返回。

代码修改的地方就这么多。

RunTime

API

可以看见多API中多了一个接口;进入看看。

可以看见除了 Id 是必须,其他参数都是有默认值,可以不用传入。

  • Id:文件的MD5值,用于接口寻找对应文件
  • w:返回的图片宽度
  • h:返回的图片高度
  • r:row 行,代表横向分割为多少行;默认为1
  • c:column 列,代表纵向分割为多少列;默认为1
  • n:代表分割后取第N个图片
上传

惯例,首先上传一个图片。

访问

访问地址,可以使用原来的也可以使用新的地址,新的地址无非就是在后面加上“/img”

压缩

上面是改变宽度和高度后的结果;你可以右键保存图片看看图片是否是被改变了。

剪切

再来看看剪切的效果:

说说原理:

再来一张:

这样也就实现了,服务器端一张图片;客户端无数张图片;可以根据需求进行分割压缩;当然复杂一点你还可以加上一些特效;比如模糊;水印等等;这些服务端都可以做。

END

资源

[WebApi] 捣鼓一个资源管理器--服务器端分割压缩图片

下一章

下章准备把这些现有的功能进行组合,做一个管理界面;那样就可以在客户端管理服务端数据了;贼爽!

========================================================

作者:qiujuer

博客:blog.csdn.net/qiujuer

网站:www.qiujuer.net

开源库:Genius-Android

转载请注明出处:http://blog.csdn.net/qiujuer/article/details/41826865

========================================================

时间: 2024-12-10 21:46:38

[WebApi] 捣鼓一个资源管理器--服务器端分割压缩图片的相关文章

[WebApi] 捣鼓一个资源管理器--数据库辅助服务器文件访问

<打造一个网站或者其他网络应用的文件管理接口(WebApi)第四章"数据库辅助服务器文件访问"> ======================================================== 作者:qiujuer 博客:blog.csdn.net/qiujuer 网站:www.qiujuer.net 开源库:Genius-Android 转载请注明出处: http://blog.csdn.net/qiujuer/article/details/41721

[WebApi] 捣鼓一个资源管理器--多文件上传

<打造一个网站或者其他网络应用的文件管理接口(WebApi)第二章"多文件上传"> ======================================================== 作者:qiujuer 博客:blog.csdn.net/qiujuer 网站:www.qiujuer.net 开源库:Genius-Android 转载请注明出处:http://blog.csdn.net/qiujuer/article/details/41675299 ====

[WebApi] 捣鼓一个资源管理器--多文件上传+数据库辅助

<打造一个网站或者其他网络应用的文件管理接口(WebApi)第三章"多文件上传+数据库辅助存储"> ======================================================== 作者:qiujuer 博客:blog.csdn.net/qiujuer 网站:www.qiujuer.net 开源库:Genius-Android 转载请注明出处: http://blog.csdn.net/qiujuer/article/details/4172

[WebApi] 捣鼓一个资源管理器--文件下载

<打造一个网站或者其他网络应用的文件管理接口(WebApi)第一章--之-- "文件下载" > ======================================================== 作者:qiujuer 博客:blog.csdn.net/qiujuer 网站:www.qiujuer.net 开源库:Genius-Android 转载请注明出处:blog.csdn.net/qiujuer/article/details/41621781 =====

更改win7资源管理器启动位置

打开资源管理器属性,在目标(T)后边加上: /e,::{20D04FE0-3AEA-1069-A2D8-08002B30309D} 俺滴笨笨原本目标(T)是: %windir%\explorer.exe  -----默认打开的是“库” 添加后: %windir%\explorer.exe /e,::{20D04FE0-3AEA-1069-A2D8-08002B30309D}  ----打开的是“计算机” /N,::{450D8FBA-AD25-11D0-98A8-0800361B1103}  

Cocos2d-x 3.2 Lua示例 AssetsManagerTest(资源管理器)

Cocos2d-x 3.2 Lua示例 AssetsManagerTest(资源管理器) 本篇博客介绍Cocos2d-x 为我们提供的一个类--AssetsManager在Lua中的使用例子,效果如下图: Cocos2d-x 给出的例子是AssetsManagerTest,进入会发现三个菜单项: enter reset update enter是进入场景,reset是删除本地版本,重新设置,update就是更新资源文件. 笔者使用LDT打开lua-tests测试项目: 在src目录下找到Asse

windows资源管理器(只能看,不能用)

实现Windows资源管理器 问题描述 Windows资源管理器是用来管理计算机资源的窗口,电脑里所有的文件都可以在资源管理器里找到,可以在资源管理器里查看文件夹的分层结构,可以利用资源管理器快速进行文件和文件夹的操作.例如,磁盘(根).目录.不同类型的文件. 其中,文件信息包括文件名.类型.创建时间.文件大小等:磁盘信息包括磁盘名称.总大小.可用空间等:目录信息包括目录名称.修改日期.大小.对象数等. 基本要求 (1)构造一个空的资源管理器: (2)新建/删除磁盘: (3)在当前选择目录下新建

使用Windows Form 制作一个简易资源管理器

自制一个简易资源管理器----TreeView控件 第一步.新建project,进行基本设置:(Set as StartUp Project:View/Toolbox/TreeView) 第二步.开始添加节点 添加命名空间using System.IO; 1 using System; 2 using System.Collections.Generic; 3 using System.ComponentModel; 4 using System.Data; 5 using System.Dra

自己动手做一个小型“资源管理器”吧

自己动手做一个小型“资源管理器”吧 注:tvDirectory是treeView控件,lvDirectory是listView控件 首先搭建一下界面: 左边是treeView控件,右边是listView控件.(listView的网格线只需把GridLins设置成True就可以了.) 由于要用到IO流,所以别忘了导入命名空间:using System.IO; 我们只要创建一个文件类就可以了: 1 public class MyFile 2 { 3 //文件长度 4 public float Fil