需求:
需要将用户后买的图片批量下载打包压缩,并且分不同的文件夹(因:购买了多个用户的图片情况)
文章中用到了一个第三方的类库,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); //文件urlif (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 长图片点击直接下载的功能,可以删除部分逻辑实现,不同文件夹压缩图片功能。
该压缩并非会压缩图片本身,解压后,图片的大小跟实际大小一致。