新工作,第一个小任务,制作一个点击下载图片的功能。并提供批量下载操作。图片是字节流的形式,存放在数据库中的。
为了避免直接从数据库中,下载失败,会在本地保存一份。
进行压缩的是SharpZip这个压缩帮助类。
首先,创建一个实体,用来存放字节流这些
public class ATLRLAttachment { /// <summary> /// 字节流 /// </summary> public byte[] FileContent { get; set; } /// <summary> /// 类型 /// </summary> public string FileExt { get; set; } /// <summary> /// 名称 /// </summary> public string FileName { get; set; } }
主要是针对这个实体,进行的字节流和名称的读取。因为要自动保存,而且这个功能是可选的,所以我用一个枚举来控制,是否可以执行这个方法。
定义枚举如下:
/// <summary> /// 是否自动保存 /// add by chenxy 16.3.10 /// </summary> public enum IsSaveImage { Save = 0, NotSave = 1 }
我是本地机进行的测试,所以字节流模拟工作是从图片进行转换的。那么加上这个图片转换方法。
/// <summary> /// 通过图片地址将图片转换成字节流 /// add by chenxy 16.3.10 /// </summary> /// <param name="url">图片地址</param> /// <returns>字节流</returns> public byte[] GetImageByte(string url) { FileStream fs = new FileStream(url, FileMode.Open); byte[] byData = new byte[fs.Length]; fs.Read(byData, 0, byData.Length); fs.Close(); return byData; }
打开图片,进行缓冲区,然后把字节流返回。比较懒,没做异常处理。
接下来,是临时保存功能。
/// <summary> /// 图片临时保存功能 /// add by chenxy 16.3.10 /// <param name="saveByte">字节流</param> /// <param name="strName">图片名称</param> /// <param name="strExt">图片后缀</param> /// <returns>文件路径</returns> /// </summary> public string SaveImage(byte[] saveByte, string strName, string strExt) { string path = AppDomain.CurrentDomain.BaseDirectory; string url = string.Format(@"{0}TemporaryImage", path); path = string.Format(@"{0}\\{1}", url, strName); //判断目录 if (!Directory.Exists(url)) { Directory.CreateDirectory(url); } //判断文件 if (File.Exists(path)) { File.Delete(path); } MemoryStream fs = new MemoryStream(saveByte); Image img = Image.FromStream(fs); ImageFormat imgFormat = ImageFormat.Jpeg; switch (strExt) { case ".bmp": imgFormat = ImageFormat.Bmp; break; case ".png": imgFormat = ImageFormat.Png; break; case ".gif": imgFormat = ImageFormat.Gif; break; } img.Save(path, imgFormat); return path; }
Directory 操作目录,File 操作文件,然后用Image进行最后的保存图片。
然后是单个下载功能代码
public void ImageDown(HttpContext context, ATLRLAttachment model, IsSaveImage save) { #region 验证方法 if (model.FileContent == null || model.FileContent.Length < 1) { ErrorMessage(context, "下载链接中没有对应的图片"); return; } #endregion #region 是否临时保存 if (save == IsSaveImage.Save) { string strUrl = SaveImage(model.FileContent, model.FileName); model.FileContent = GetImageByte(strUrl); } #endregion context.Response.AddHeader("Content-Disposition", string.Format("attachment;filename={0}", model.FileName)); context.Response.ContentType = string.Format("image/{0}", model.FileExt.Replace(".", "")); context.Response.BinaryWrite(model.FileContent); context.Response.Flush(); context.Response.Close(); }
其中ErrorMessage 是提示信息。
public void ErrorMessage(HttpContext context, string strMsg) { context.Response.Write(string.Format("<script language=javascript>alert('{0}');</" + "script>", strMsg)); context.Response.Write("<script language=javascript>history.go(-1);</script>"); context.Response.End(); }
批量下载使用的重载,通过传递IEnumerable 进行批量压缩。
/// <summary> /// 批量下载 /// add by chenxy 16.3.10 /// </summary> /// <param name="context">HTTP请求</param> /// <param name="models">下载集合</param> public void ImageDown(HttpContext context, IEnumerable<ATLRLAttachment> models, IsSaveImage save) { string FileToZip = DateTime.Now.ToString("yyyymmdd") + ".zip"; string path = AppDomain.CurrentDomain.BaseDirectory; string url = string.Format(@"{0}TemporaryImage", path); path = string.Format(@"{0}\\{1}", url, FileToZip); BatchDeleteZip(url); using (FileStream ms = File.Create(path)) { using (ZipOutputStream zip = new ZipOutputStream(ms)) { zip.SetLevel(9); int itFileNameNum = 0; foreach (ATLRLAttachment m in models) { #region 修改重名文件 if (models.Where(p => p.FileName == m.FileName).Count() > 1) { itFileNameNum++; try { m.FileName = m.FileName.Insert(m.FileName.IndexOf("."), string.Format("_{0}", itFileNameNum)); } catch (ArgumentNullException) { ErrorMessage(context, string.Format("文件名:{0},格式错误,未包含后缀连接符.", m.FileName)); return; } } #endregion #region 是否临时保存 if (save == IsSaveImage.Save) { string strUrl = SaveImage(m.FileContent, m.FileName, m.FileExt); m.FileContent = GetImageByte(strUrl); //判断文件 if (File.Exists(strUrl)) { File.Delete(strUrl); } } #endregion //如果没有图片就跳过 if (m.FileContent == null || m.FileContent.Length < 1) { continue; } ZipEntry entry = new ZipEntry(m.FileName); zip.PutNextEntry(entry); zip.Write(m.FileContent, 0, m.FileContent.Length); } zip.Finish(); zip.Close(); } } FileInfo fileInfo = new FileInfo(path); context.Response.Clear(); context.Response.ClearContent(); context.Response.ClearHeaders(); context.Response.AddHeader("Content-Disposition", string.Format("attachment;filename={0}.zip", DateTime.Now.ToString("yyyyMMdd"))); context.Response.AddHeader("Content-Length", fileInfo.Length.ToString()); context.Response.AddHeader("Content-Transfer-Encoding", "binary"); context.Response.ContentType = "application/octet-stream"; context.Response.ContentEncoding = System.Text.Encoding.GetEncoding("utf-8"); context.Response.WriteFile(fileInfo.FullName); context.Response.Flush(); context.Response.End(); }
批量下载需要删除文件夹,有一个遍历目录并删除文件的方法
/// <summary> /// 批量删除压缩包 /// add by chenxy 16.3.15 /// </summary> /// <param name="strUrl">压缩包路径</param> public void BatchDeleteZip(string strUrl) { //判断路径是否为空 if (string.IsNullOrEmpty(strUrl)) { throw new ArgumentNullException("文件目录为空"); } //判断是否有目录 if (!Directory.Exists(strUrl)) { return; } //获取目录下所有文件 string[] strFiles = Directory.GetFiles(strUrl); //判断文件时间长短 foreach (string strfile in strFiles) { FileInfo info = new FileInfo(strfile); if (info.CreationTime.DistanceToday() >= 1) { File.Delete(info.FullName); } } }
最后就没的说了,就是普通的调用测试,写的比较乱,勉强能看懂
public void ProcessRequest(HttpContext context) { // string path = AppDomain.CurrentDomain.BaseDirectory; //byte[] result = GetImageByte(string.Format(@"{0}0.jpg", path)); //path = SaveImage(result,"0.jpg"); //result = GetImageByte(path); byte[] result = GetImageByte(@"D://111.jpg"); ImageDown(context, new ATLRLAttachment { FileContent = result, FileExt = ".jpg", FileName = "ce.jpg" }, IsSaveImage.Save); // File.Delete(path); return; //ImageDown(context, result, "imageName.jpg", "jpg"); var list = new[] { new ATLRLAttachment { FileContent = result, FileExt = ".jpg", FileName = "Name.jpg" }, new ATLRLAttachment { FileContent = result, FileExt = ".jpg", FileName = "Name.jpg" } }; ImageDown(context, list, IsSaveImage.Save); return; }
程序员最有利的武器,就是谷歌,百度。做这个的时候,我就想,用IO流进行保存。但是忘记方法名了,就一直尴尬。
下载地址:https://coding.net/u/chenxygx/p/CodeSave/git/blob/master/Handler1.ashx.cs
记录一下,免得以后再去百度了。By~