最近在开发一套系统,很多地方用到了缩略图,然而不同的地方用到的尺寸又不一样,上传的时候生成缩略图就没有意义了,因为你不知道会使用到哪些尺寸,于是想到即时生成的办法,前端判断图片是否存在,如果不存在则调用接口生成缩略图,同时接口返回缩略图的数据流。
本来功能都开发完成,可以达到目的,但是在会员头像使用Png生成缩略图是遇到了一个问题,就是生成的缩略图不是透明的,变成黑底色了。更奇怪的问题是并不是所有png图片都这样,同一张图片在不同的地方也有不一样的效果。
没有修改之前的代码如下:
/// <summary>
/// 访问图片,接口调用方式 https://您的域名/WebApi/common/200/image%2F2022-06%2Fbb372369c3ad4d458ad2aee6c00ca4bd.png
///其中200是图片宽度,后面是图片的相对路径
/// </summary>
/// <param name="width">所访问图片的宽度,高度自动缩放,大于原图尺寸或者小于等于0返回原图</param>
/// <param name="name">所要访问图片的名称或者相对地址</param>
/// <returns>图片</returns>
[HttpGet]
[Route("{width}/{name}")]
public IActionResult GetImage(int width, string name)
{
var errorImage = "/static/common/images/404.png";//没有找到图片
if(name.IsEmptyString())
{
name = errorImage;
}
else
{
name = HttpUtility.UrlDecode(name, Encoding.GetEncoding("utf-8"));
name = name.Replace("/", "\\");
if(name.StartsWith("\\")) { name = name.Substring(1); }
}
var contentTypeStr = "image/jpeg";
var ext = Path.GetExtension(name);
//未知的图片类型
if(!FileHelper.IsImageExt(ext))
{
name = errorImage;
}
else
{
contentTypeStr = FileHelper.GetContentType(ext);
}
bool isThum = false;//是否是缩略图
var thumname = name;//缩略图路径
bool saveThum = false;
//原图
if(width <= 0)
{
using(var sw = objectStorage.GetObject(name))
{
var bytes = new byte[sw.Length];
sw.Read(bytes, 0, bytes.Length);
sw.Close();
return new FileContentResult(bytes, contentTypeStr);
}
}
else
{
thumname = name.Replace(ext, "_" + width + ext);
isThum = true;
}
if(name != errorImage && !objectStorage.ExistObject(name))
{
name = errorImage;
}
if(isThum && !objectStorage.ExistObject(thumname))
{
saveThum = true;
}
//缩小图片
using(var imgBmp = new Bitmap(Image.FromStream(objectStorage.GetObject(name))))
{
//找到新尺寸
var oWidth = imgBmp.Width;
var oHeight = imgBmp.Height;
var height = oHeight;
if(width > oWidth)
{
width = oWidth;
}
else
{
height = width * oHeight / oWidth;
}
var newImg = new Bitmap(imgBmp, width, height);
newImg.SetResolution(72, 72);
var ms = new MemoryStream();
newImg.Save(ms, ImageFormat.Bmp);
if(saveThum)
{
//这里是调用的类似OSS保存图片的方法
objectStorage.PutObject(thumname, ms);
ms.Position = 0;
}
var bytes = ms.GetBuffer();
ms.Close();
return new FileContentResult(bytes, contentTypeStr);
}
}
代码如上,表面上看起来看不出来问题,后来我认真检查了一下代码,发现newImg.Save(ms, ImageFormat.Bmp);这句代码有点问题,为什么是固定的bmp格式,于是我将这句代码改成如下代码:
switch(ext.ToLower())
{
case ".jpg":
case ".jpeg":
case ".jpe":
case ".jfif":
newImg.Save(ms, ImageFormat.Jpeg);
break;
case ".png":
newImg.Save(ms, ImageFormat.Png);
break;
case ".gif":
newImg.Save(ms, ImageFormat.Gif);
break;
case ".tif":
case ".tiff":
newImg.Save(ms, ImageFormat.Tiff);
break;
case ".bmp":
case ".wbmp":
newImg.Save(ms, ImageFormat.Bmp);
break;
default:
newImg.Save(ms, ImageFormat.Jpeg);
break;
}
问题解决,原来文件流里面也是要指定文件保存的格式的,不然就会出现想不到的问题。
浙公网安备 33010602011771号