.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 长图片点击直接下载的功能,可以删除部分逻辑实现,不同文件夹压缩图片功能。
该压缩并非会压缩图片本身,解压后,图片的大小跟实际大小一致。