.net webapi 接收图片保存到服务器,并居中剪裁压缩图片
每天解决一些c#小问题,在写微信小程序,或者一些手机软件接口,我们经常要用到上传图片到服务器,或者使用图床去保存我们的图片。
这次就简单明了的来梳理一下如何实现图片的接受和对接受到的图片进行一些处理。
一、实现图片的接收
1.首先要明确现在大部分前端的传输图片的统一规范都是通过POST请求+form表单提交文件的形式
通过 HttpContext.Current.Request.Files 获取请求头里面的文件
然后获取文件流,通过编译文件流另存为文件,保留到指定目录中
其中指定目录必须要现在系统中存在,不然会报错,这里通过前端传输suffix后缀的方式生成文件路径,可以自己写方法判断
上代码,这里是上传一张图片的示例,多张图片可自己更改添加遍历即可,我用的是时间戳命名
[HttpPost,Route("UpLoadImageFiles")]
public string UpLoadImageFiles(string suffix)//suffix是后缀的意思,可以自己判断,也可以前端传输
{
var files = HttpContext.Current.Request.Files;//首先先确定请求里夹带的文件数量
if (files.AllKeys.Any())//如果存在文件
{
using (HttpClient client = new HttpClient())
{
HttpContextBase HttpContext = (HttpContextBase)Request.Properties["MS_HttpContext"];
var text = HttpContext.Request.Files[0].InputStream;//获取到文件流
string path = HttpContext.Request.MapPath("~/");//获取你的根目录
string datetime = GetTimeStamp();
string strPath = path + "File\\" + datetime + suffix;//这里要注意的是先要建立File文件夹,不然会报错,也可以自己写一个检测文件夹,这里就先不赘述
StreamHelp.StreamToFile(text,strPath);//需要用到下一步的帮助类将其保存为文件
//------------------以下是剪裁和压缩图片代码不需要的可以略过
string imgPath = path + "File\\img\\" + datetime + suffix;
ImageHelp img = new ImageHelp(strPath);
img.GetReducedImage(0.8, imgPath);
}
return "添加成功";
}
return "无文件";
}
///获取时间戳的方法
private string GetTimeStamp()
{
TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0);
return Convert.ToInt64(ts.TotalMilliseconds).ToString();
}
2.获取到文件流后,需要一个帮助类将其转化为文件保存起来,我把它封装了一下StreamHelp.cs
public static class StreamHelp
{
/// <summary>
/// 流转文件
/// </summary>
/// <param name="stream"></param>
/// <param name="fileName"></param>
public static void StreamToFile(Stream stream, string fileName)
{
// 把 Stream 转换成 byte[]
byte[] bytes = new byte[stream.Length];
stream.Read(bytes, 0, bytes.Length);
// 设置当前流的位置为流的开始
stream.Seek(0, SeekOrigin.Begin);
// 把 byte[] 写入文件
FileStream fs = new FileStream(fileName, FileMode.Create);
BinaryWriter bw = new BinaryWriter(fs);
bw.Write(bytes);
bw.Close();
fs.Close();
}
/// <summary>
/// 文件转流
/// </summary>
/// <param name="fileName"></param>
/// <returns></returns>
public static Stream FileToStream(string fileName)
{
// 打开文件
FileStream fileStream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read);
// 读取文件的 byte[]
byte[] bytes = new byte[fileStream.Length];
fileStream.Read(bytes, 0, bytes.Length);
fileStream.Close();
// 把 byte[] 转换成 Stream
Stream stream = new MemoryStream(bytes);
return stream;
}
/// <summary>
/// 流转Bytes
/// </summary>
/// <param name="stream"></param>
/// <returns></returns>
public static byte[] StreamToBytes(Stream stream)
{
byte[] bytes = new byte[stream.Length];
stream.Read(bytes, 0, bytes.Length);
// 设置当前流的位置为流的开始
stream.Seek(0, SeekOrigin.Begin);
return bytes;
}
/// <summary>
/// Bytes转流
/// </summary>
/// <param name="bytes"></param>
/// <returns></returns>
public static Stream BytesToStream(byte[] bytes)
{
Stream stream = new MemoryStream(bytes);
return stream;
}
}
二、图片的裁剪
接收图片的步奏这样就已经完成了,图片会保存到你自定义的文件夹中,接下来就是压缩图片
为了方便我将剪裁和压缩图片放在了同一个类中ImageHelp
首先是裁剪,我需要的是居中裁剪,也就是无论什么形状的图片传过来,都会裁剪成正方形
ImageTailor(string path)
剪裁使用的方法就是重画,使用Graphics.DrawImage(),新建一个正方形画布
首先先做长宽对比取最小的的边,然后把长的边剪裁,(bmp.Width - bmp.Height) / 2
这里通过改变原图的起始点进行检查,不用改变原图的长宽,防止图片形变。
GetReducedImage(double Percent, string targetFilePath)
然后通过百分比压缩图片,推荐80%就足够了。
public class ImageHelp
{
public Image ResourceImage;
private int ImageWidth;
private int ImageHeight;
public string ErrMessage;
/// <summary>
/// 类的构造函数
/// </summary>
/// <param name="ImageFileName">图片文件的全路径名称</param>
public ImageHelp(string ImageFileName)
{
var BeImage = Image.FromFile(ImageFileName);
ResourceImage = ImageTailor(ImageFileName);
ErrMessage = "";
}
public bool ThumbnailCallback()
{
return false;
}
/// <summary>
/// 裁剪居中
/// </summary>
/// <param name="path"></param>
/// <returns></returns>
public Image ImageTailor(string path)
{
Bitmap bmp = new Bitmap(path);
var width = 0;
var height = 0;
var x = 0;
var y = 0;
if (bmp.Width > bmp.Height)
{
width = bmp.Height;
height = bmp.Height;
y = 0;
x = (bmp.Width - bmp.Height) / 2;
}
else
{
width = bmp.Width;
height = bmp.Width;
y = (bmp.Height - bmp.Width) / 2;
x = 0;
}
Bitmap newbm = new Bitmap(width, height);
Graphics g = Graphics.FromImage(newbm);
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.SmoothingMode = SmoothingMode.HighQuality;
g.CompositingQuality = CompositingQuality.HighQuality;
//前Rectangle代表画布大小,后Rectangle代表裁剪后右边留下的区域
g.DrawImage(bmp, new Rectangle(0, 0, width, height), new Rectangle(x, y, width, height), GraphicsUnit.Pixel);
g.Dispose();
return newbm;
}
/// <summary>
/// 生成缩略图重载方法1,返回缩略图的Image对象
/// </summary>
/// <param name="Width">缩略图的宽度</param>
/// <param name="Height">缩略图的高度</param>
/// <returns>缩略图的Image对象</returns>
public Image GetReducedImage(int Width, int Height)
{
try
{
Image ReducedImage;
Image.GetThumbnailImageAbort callb = new Image.GetThumbnailImageAbort(ThumbnailCallback);
ReducedImage = ResourceImage.GetThumbnailImage(Width, Height, callb, IntPtr.Zero);
return ReducedImage;
}
catch (Exception e)
{
ErrMessage = e.Message;
return null;
}
}
/// <summary>
/// 生成缩略图重载方法2,将缩略图文件保存到指定的路径
/// </summary>
/// <param name="Width">缩略图的宽度</param>
/// <param name="Height">缩略图的高度</param>
/// <param name="targetFilePath">缩略图保存的全文件名,(带路径),参数格式:D:Images ilename.jpg</param>
/// <returns>成功返回true,否则返回false</returns>
public bool GetReducedImage(int Width, int Height, string targetFilePath)
{
try
{
Image ReducedImage;
Image.GetThumbnailImageAbort callb = new Image.GetThumbnailImageAbort(ThumbnailCallback);
ReducedImage = ResourceImage.GetThumbnailImage(Width, Height, callb, IntPtr.Zero);
ReducedImage.Save(@targetFilePath, ImageFormat.Jpeg);
ReducedImage.Dispose();
return true;
}
catch (Exception e)
{
ErrMessage = e.Message;
return false;
}
}
/// <summary>
/// 生成缩略图重载方法3,返回缩略图的Image对象
/// </summary>
/// <param name="Percent">缩略图的宽度百分比 如:需要百分之80,就填0.8</param>
/// <returns>缩略图的Image对象</returns>
public Image GetReducedImage(double Percent)
{
try
{
Image ReducedImage;
Image.GetThumbnailImageAbort callb = new Image.GetThumbnailImageAbort(ThumbnailCallback);
ImageWidth = Convert.ToInt32(ResourceImage.Width * Percent);
ImageHeight = Convert.ToInt32(ResourceImage.Height * Percent);
ReducedImage = ResourceImage.GetThumbnailImage(ImageWidth, ImageHeight, callb, IntPtr.Zero);
return ReducedImage;
}
catch (Exception e)
{
ErrMessage = e.Message;
return null;
}
}
/// <summary>
/// 生成缩略图重载方法4,返回缩略图的Image对象
/// </summary>
/// <param name="Percent">缩略图的宽度百分比 如:需要百分之80,就填0.8</param>
/// <param name="targetFilePath">缩略图保存的全文件名,(带路径),参数格式:D:Images ilename.jpg</param>
/// <returns>成功返回true,否则返回false</returns>
public bool GetReducedImage(double Percent, string targetFilePath)
{
try
{
Image ReducedImage;
Image.GetThumbnailImageAbort callb = new Image.GetThumbnailImageAbort(ThumbnailCallback);
ImageWidth = Convert.ToInt32(ResourceImage.Width * Percent);
ImageHeight = Convert.ToInt32(ResourceImage.Height * Percent);
ReducedImage = ResourceImage.GetThumbnailImage(ImageWidth, ImageHeight, callb, IntPtr.Zero);
ReducedImage.Save(@targetFilePath, ImageFormat.Jpeg);
ReducedImage.Dispose();
return true;
}
catch (Exception e)
{
ErrMessage = e.Message;
return false;
}
}
}