每天解決一些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;
}
}
}