服务器之家

服务器之家 > 正文

Asp.net mvc实时生成缩率图到硬盘

时间:2020-01-07 13:36     来源/作者:onestraw

对于缩率图的处理是在图片上传到服务器之后,同步生成两张不同尺寸的缩率供前端调用,刚开始还能满足需求,慢慢的随着前端展示的多样化,缩率图已不能前端展示的需求,所以考虑做一个实时生成图片缩率图服务。

每次调用实时生成缩率图,不缓存着实有点浪费,所以在生成缩率的同时缓存到硬盘一份,效率提高很多。

之前从网上看了一下有人用nginx + lua实现的,效率那是没什么可说的,但是时间紧迫,自己也没时间去研究,所以暂时先用aps.net mvc4来实现 一个,以后有时间了,再慢慢修改。

用自己熟悉的.net性能可能差那么一点点,但是实现速度快,保证可以在极端的时间内上线,并且在功能上更强。

思路很简单,就是根据请求,判断需要的缩率图是否已存在于硬盘上,如果有直接返回,没有则下载原图,并生成缩率图到本地,返回给客户端。

下面直接粘贴代码片段:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
/// <summary>
 /// 生成图片缩率图Action
 /// </summary>
 /// <param name="p">原图url</param>
 /// <param name="id">图片尺寸以及生成缩率图的类型</param>
 /// <returns></returns>
 [ValidateInput(false)]
 public ActionResult Index(string p, string id)
 {
  if (string.IsNullOrEmpty(p))
  {
  return new HttpStatusCodeResult(404);
  }
 
  string oPath = Regex.Replace(p, @"http[s]?://(.*?)/", "/", RegexOptions.IgnoreCase);
  int? oWidth = 200, oHeight = 200;
  int cutMode = 3;
  string pPath;
  string oDir;
 
  if (!string.IsNullOrEmpty(id))
  {
  string[] ss = id.Split(new char[] { '_' }, StringSplitOptions.RemoveEmptyEntries);
  if (ss.Length < 2)
  {
   return new HttpStatusCodeResult(404);
  }
  if (ss.Length > 2)
  {
   cutMode = int.Parse(ss[2]);
  }
  oPath = oPath.Insert(oPath.LastIndexOf('/') + 1, string.Format("{0}_{1}_{2}_", ss[0], ss[1], cutMode));
  oWidth = int.Parse(ss[0]);
  oHeight = int.Parse(ss[1]);
  }
 
  pPath = Server.MapPath(oPath);
  oDir = Path.GetDirectoryName(pPath);
 
  if (!System.IO.File.Exists(pPath))
  {
  byte[] imagebytes = FileHelper.DownLoadFile(p);
  if (!Directory.Exists(oDir))
  {
   Directory.CreateDirectory(oDir);
  }
  FileHelper.MakeThumbnail(FileHelper.BytToImg(imagebytes), oWidth.Value, oHeight.Value, (ThumbnailMode)cutMode, pPath, true);
  }
 
  return File(pPath, FileHelper.GetContentTypeByExtension(Path.GetExtension(pPath).ToLower()));
 }

辅助方法:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
public class FileHelper
{
 /// <summary>
/// 图片后缀和ContentType对应字典
/// </summary>
static Dictionary<string, string> extensionContentTypeDic;
 
static FileHelper()
{
 if (extensionContentTypeDic == null)
 {
 //.jpg", ".png", ".gif", ".jpeg
 extensionContentTypeDic = new Dictionary<string, string>();
 extensionContentTypeDic.Add(".jpg", "image/jpeg");
 extensionContentTypeDic.Add(".png", "image/png");
 extensionContentTypeDic.Add(".gif", "image/gif");
 extensionContentTypeDic.Add(".jpeg", "image/jpeg");
 }
}
/// <summary>
/// 根据后缀名获取extension
/// </summary>
/// <param name="extension"></param>
/// <returns></returns>
public static string GetContentTypeByExtension(string extension)
{
 if (extensionContentTypeDic.ContainsKey(extension))
 {
 return extensionContentTypeDic[extension];
 }
 return null;
}
 
/// <summary >
/// 将Image对象转化成二进制流
/// </summary >
/// <param name="image" > </param >
/// <returns > </returns >
public static byte[] ImageToByteArray(Image image)
{
 MemoryStream imageStream = new MemoryStream();
 Bitmap bmp = new Bitmap(image.Width, image.Height);
 Graphics g = Graphics.FromImage(bmp);
 g.DrawImage(image, new System.Drawing.Rectangle(0, 0, image.Width, image.Height));
 try
 {
 bmp.Save(imageStream, image.RawFormat);
 }
 catch (Exception e)
 {
 
 bmp.Save(imageStream, System.Drawing.Imaging.ImageFormat.Jpeg);
 }
 byte[] byteImg = imageStream.GetBuffer();
 bmp.Dispose();
 g.Dispose();
 imageStream.Close();
 return byteImg;
}
 
/// <summary>
/// 字节流转换成图片
/// </summary>
/// <param name="byt">要转换的字节流</param>
/// <returns>转换得到的Image对象</returns>
public static Image BytToImg(byte[] byt)
{
 MemoryStream ms = new MemoryStream(byt);
 Image img = Image.FromStream(ms);
 ms.Close();
 return img;
}
 
/// <summary>
/// 生成缩率图
/// </summary>
/// <param name="originalImage">原始图片Image</param>
/// <param name="width">缩率图宽</param>
/// <param name="height">缩率图高</param>
/// <param name="mode">生成缩率图的方式</param>
/// <param name="thumbnailPath">缩率图存放的地址</param>
public static Image MakeThumbnail(Image originalImage, int width, int height, ThumbnailMode mode, string thumbnailPath, bool isSave = true)
{
 int towidth = width;
 int toheight = height;
 
 int x = 0;
 int y = 0;
 int ow = originalImage.Width;
 int oh = originalImage.Height;
 switch (mode)
 {
 case ThumbnailMode.HW://指定高宽缩放(可能变形)  
  break;
 case ThumbnailMode.W://指定宽,高按比例  
  toheight = originalImage.Height * width / originalImage.Width;
  break;
 case ThumbnailMode.H://指定高,宽按比例
  towidth = originalImage.Width * height / originalImage.Height;
  break;
 case ThumbnailMode.Cut://指定高宽裁减(不变形)  
  if ((double)originalImage.Width / (double)originalImage.Height > (double)towidth / (double)toheight)
  {
  oh = originalImage.Height;
  ow = originalImage.Height * towidth / toheight;
  y = 0;
  x = (originalImage.Width - ow) / 2;
  }
  else
  {
  ow = originalImage.Width;
  oh = originalImage.Width * height / towidth;
  x = 0;
  y = (originalImage.Height - oh) / 2;
  }
  break;
 
 default:
  break;
 }
 
 //新建一个bmp图片
 System.Drawing.Image bitmap = new System.Drawing.Bitmap(towidth, toheight);
 //新建一个画板
 Graphics g = System.Drawing.Graphics.FromImage(bitmap);
 //设置高质量插值法
 g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.High;
 //设置高质量,低速度呈现平滑程度
 g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
 //清空画布并以透明背景色填充
 g.Clear(Color.Transparent);
 //在指定位置并且按指定大小绘制原图片的指定部分
 g.DrawImage(originalImage, new Rectangle(0, 0, towidth, toheight),
 new Rectangle(x, y, ow, oh),
 GraphicsUnit.Pixel);
 if (!isSave)
 {
 return bitmap;
 }
 try
 {
 //以jpg格式保存缩略图
 //bitmap.Save(thumbnailPath, bitmap.RawFormat);
 bitmap.Save(thumbnailPath, ImageFormat.Jpeg);
 return bitmap;
 
 }
 catch (System.Exception e)
 {
 throw e;
 }
 finally
 {
 originalImage.Dispose();
 bitmap.Dispose();
 g.Dispose();
 }
 return null;
}
 
 
/// <summary>
/// 下载指定文件
/// </summary>
/// <param name="remoteUrl"></param>
/// <param name="ss"></param>
public static byte[] DownLoadFile(string remoteUrl)
{
 WebClient wc = new WebClient();
 try
 {
 return wc.DownloadData(remoteUrl);
 }
 catch (Exception e)
 {
 throw new Exception("下载文件失败");
 }
}
 
}
 
public enum ThumbnailMode
{
/// <summary>
/// 指定高宽缩放(可能变形)
/// </summary>
HW,
/// <summary>
/// 指定高,宽按比例
/// </summary>
H,
/// <summary>
/// 指定宽,高按比例
/// </summary>
W,
/// <summary>
/// 指定高宽裁减(不变形)
/// </summary>
Cut,
 
}

访问方式:

http://www.souji8.com/Home/Index/{width}_{height}_{ThumMode}?p={imageUrl}

{imageUrl}:目标图片地址

{ThumMode}: 1:指定高宽按比例、2:指定宽,高按比例、3:指定高宽裁减(不变形)

{Width}:期望图片宽

{Height}:期望图片高

以上就是本文的全部内容,希望对大家的学习有所帮助。

标签:

相关文章

热门资讯

玄元剑仙肉身有什么用 玄元剑仙肉身境界等级划分
玄元剑仙肉身有什么用 玄元剑仙肉身境界等级划分 2019-06-21
男生常说24816是什么意思?女生说13579是什么意思?
男生常说24816是什么意思?女生说13579是什么意思? 2019-09-17
华为nova5pro和p30pro哪个好 华为nova5pro和华为p30pro对比详情
华为nova5pro和p30pro哪个好 华为nova5pro和华为p30pro对比详情 2019-06-22
配置IIS网站web服务器的安全策略配置解决方案
配置IIS网站web服务器的安全策略配置解决方案 2019-05-23
Nginx服务器究竟是怎么执行PHP项目
Nginx服务器究竟是怎么执行PHP项目 2019-05-24
返回顶部