创建并流式传输图像存档zip文件以供下载C#

时间:2012-09-24 13:12:52

标签: c# asp.net-mvc-3 zip dotnetzip

我正在使用MVC3中心爱的DotNetZip归档库来动态生成一个Zip文件,其中包含存储在数据库中的二进制文件的.png图像。然后我将生成的Zip文件流式传输给用户下载。 (我在保存到数据库之前验证图像数据,因此您可以假设所有图像数据都有效)。

public ActionResult PictureExport()
      {
           IEnumerable<UserPicture> userPictures = db.UserPicture.ToList();
           //"db" is a DataContext and UserPicture is the model used for uploaded pictures.
           DateTime today = DateTime.Now;
           string fileName = "attachment;filename=AllUploadedPicturesAsOf:" + today.ToString() + ".zip";
           this.Response.Clear();
           this.Response.ContentType = "application/zip";
           this.Response.AddHeader("Content-Disposition", fileName);

           using (ZipFile zipFile = new ZipFile())
             {
               using (MemoryStream stream = new MemoryStream())
                {
                 foreach (UserPicture userPicture in userPictures)
                  {
                     stream.Seek(0, SeekOrigin.Begin);
                     string pictureName = userPicture.Name+ ".png";
                     using (MemoryStream tempstream = new MemoryStream())
                     {
                        Image userImage = //method that returns Drawing.Image from byte[];
                        userImage.Save(tempstream, ImageFormat.Png);
                        tempstream.Seek(0, SeekOrigin.Begin);
                        stream.Seek(0, SeekOrigin.Begin);
                        tempstream.WriteTo(stream);
                     }

                     zipFile.AddEntry(pictureName, stream);
                 }

                zipFile.Save(Response.OutputStream);
              }

           }

        this.Response.End();
        return RedirectToAction("Home");
      }

此代码适用于上传和导出ONE(1)图像。但是,在将多个图像上载到数据库然后尝试将它们全部导出之后,生成的Zip文件将仅包含最新上载图像的数据。所有其他图像名称将出现在zip文件中,但它们的文件大小为0,它们只是空文件。

我猜我的问题与MemoryStreams有关(或者我错过了一些简单的东西),但据我所知,通过单步执行代码,图像被从数据库中拉出来并且正在已成功添加到zip文件中...

1 个答案:

答案 0 :(得分:4)

您对stream.Seek(0,SeekOrigin.Begin)的调用导致使用最新的图像数据在每次迭代时覆盖流的内容。试试这个:

using (ZipFile zipFile = new ZipFile())
{
    foreach (var userPicture in userPictures)
    {
        string pictureName = userPicture.Name + ".png";
        using (MemoryStream tempstream = new MemoryStream())
        {
            Image userImage = //method that returns Drawing.Image from byte[];   
            userImage.Save(tempstream, ImageFormat.Png);  
            tempstream.Seek(0, SeekOrigin.Begin);
            byte[] imageData = new byte[tempstream.Length];
            tempstream.Read(imageData, 0, imageData.Length);
            zipFile.AddEntry(pictureName, imageData);
        }
    }

    zipFile.Save(Response.OutputStream);
}