1. 程式人生 > >.NET壓縮圖片儲存

.NET壓縮圖片儲存

需求:

需要將使用者後買的圖片批量下載打包壓縮,並且分不同的資料夾(因:購買了多個使用者的圖片情況)

文章中用到了一個第三方的類庫,Nuget下載 SharpZipLib 目前用的 1.1的版本

 

效果:

 

伺服器目錄展示:

裡面對應目錄層級的圖片

 

前端提交POST請求案例:

function DownAllFile(filename, imgUrl, down) {

var urlStr = "";
//url字串 (示例資料) (注意!: 使用 '逗號' 分隔檔名和 url 地址,使用 '$' 分隔 每個檔案.)
if (filename != '' && imgUrl != '')
urlStr = filename + "," + imgUrl;

//form提交
var form = $('<form>');
form.attr('style', 'display:none');
form.attr('target', '');
form.attr('method', 'post');
form.attr('action', '/PayStripe.ashx?method=DownLoadImage'); //這裡寫對應的方法地址

var name1 = $('<input>');
name1.attr('type', 'text');
name1.attr('name', 'urlStr');
name1.attr('value', urlStr); //檔案url

if (down == "P") {
var vals = "";
$.each($('input:checkbox:checked'), function () {
vals += $(this).val() + ",";
});
var checkbox1 = $('<input>');
checkbox1.attr('type', 'text');
checkbox1.attr('name', 'coid');
checkbox1.attr('value', vals); //檔案url
form.append(checkbox1);
}
$('body').append(form);
form.append(name1);
form.submit();
form.remove();
}

 

後端實現程式碼:

//得到檔案資訊(名字,地址) (去掉最後一個 '$' , 並用 '$' 分隔字串. 取到每個檔案的檔名和路徑 )
string[] urlArray = model.urlStr.TrimEnd('$').Split('$');

//存 檔名 和 資料流
Dictionary<string, Stream> dc = new Dictionary<string, Stream>();

//取出字串中資訊 (檔名和地址)
for (int i = 0; i < urlArray.Length; i++)
{
WebClient myWebClient = new WebClient();
//使用 ',' 分隔 檔名和路徑 [0]位置是檔名, [1] 位置是路徑
string[] urlSp = urlArray[i].Split(',');
//呼叫WebClient 的 DownLoadData 方法 下載檔案
byte[] data = myWebClient.DownloadData(urlSp[1].Replace("_PB.jpg", "_B.jpg"));
Stream stream = new MemoryStream(data);//byte[] 轉換成 流

//放入 檔名 和 stream
dc.Add(urlSp[0] + ".jpg" + "," + urlSp[2], stream);//這裡指定為 .doc格式 (自己可以隨時改)

if (urlArray.Length == 1)
{
Image img = Image.FromStream(stream);
MemoryStream ms = new MemoryStream();
img.Save(ms, ImageFormat.Jpeg);
img.Dispose();
context.Response.ClearContent();
context.Response.ContentType = "application/octet-stream";
context.Response.AppendHeader("Content-Disposition", "attachment;filename=" + urlSp[0] + ".jpeg");//檔名和格式(格式可以自己定)
context.Response.ContentType = "image/jpeg";
context.Response.BinaryWrite(ms.ToArray());
return;
}
}

//呼叫壓縮方法 進行壓縮 (接收byte[] 資料)
byte[] fileBytes = ConvertZipStream(dc);

context.Response.ContentType = "application/octet-stream";
context.Response.AppendHeader("Content-Disposition", "attachment;filename=SoonnetImage.rar");//檔名和格式(格式可以自己定)
context.Response.AddHeader("Content-Length", fileBytes.Length.ToString());//檔案大小
context.Response.BinaryWrite(fileBytes); //放入byte[]
context.Response.End();
context.Response.Close();

 

 

 

/// <summary>
/// ZipStream 壓縮
/// </summary>
/// <param name="streams">Dictionary(string, Stream) 檔名和Stream</param>
/// <returns></returns>
public static byte[] ConvertZipStream(Dictionary<string, Stream> streams)
{
byte[] buffer = new byte[6500];
MemoryStream returnStream = new MemoryStream();
var zipMs = new MemoryStream();
using (ICSharpCode.SharpZipLib.Zip.ZipOutputStream zipStream = new ICSharpCode.SharpZipLib.Zip.ZipOutputStream(zipMs))
{
zipStream.SetLevel(9);//設定 壓縮等級 (9級 500KB 壓縮成了96KB)
foreach (var kv in streams)
{
string[] fileName = kv.Key.Split(',');
using (var streamInput = kv.Value)
{
zipStream.PutNextEntry(new ICSharpCode.SharpZipLib.Zip.ZipEntry(fileName[1] + "/" + fileName[0]));  //主要是這裡可以分資料夾自動壓縮
while (true)
{
var readCount = streamInput.Read(buffer, 0, buffer.Length);
if (readCount > 0)
{
zipStream.Write(buffer, 0, readCount);
}
else
{
break;
}
}
zipStream.Flush();
}
}
zipStream.Finish();
zipMs.Position = 0;
zipMs.CopyTo(returnStream, 5600);
}
returnStream.Position = 0;

//Stream轉Byte[]
byte[] returnBytes = new byte[returnStream.Length];
returnStream.Read(returnBytes, 0, returnBytes.Length);
returnStream.Seek(0, SeekOrigin.Begin);

return returnBytes;
}

 

注:

文章中程式碼有牽扯到 1 長圖片點選直接下載的功能,可以刪除部分邏輯實現,不同資料夾壓縮圖片功能。

該壓縮並非會壓縮圖片本身,解壓後,圖片的大小跟實際大小一致。