如何使用ASP.NET创建和填充ZIP文件?

27

需要动态地将一些文件打包成.zip文件,以创建SCORM包,有人知道如何使用代码实现吗?是否可以在.zip文件内动态地构建文件夹结构?


可能是重复的问题:使用 System.IO.Packaging 生成 ZIP 文件 - user1228
9个回答

22

DotNetZip非常适合这种情况。

您可以直接将zip写入Response.OutputStream。代码看起来像这样:

    Response.Clear();
    Response.BufferOutput = false; // for large files...
    System.Web.HttpContext c= System.Web.HttpContext.Current;
    String ReadmeText= "Hello!\n\nThis is a README..." + DateTime.Now.ToString("G"); 
    string archiveName= String.Format("archive-{0}.zip", 
                                      DateTime.Now.ToString("yyyy-MMM-dd-HHmmss")); 
    Response.ContentType = "application/zip";
    Response.AddHeader("content-disposition", "filename=" + archiveName);

    using (ZipFile zip = new ZipFile())
    {
        // filesToInclude is an IEnumerable<String>, like String[] or List<String>
        zip.AddFiles(filesToInclude, "files");            

        // Add a file from a string
        zip.AddEntry("Readme.txt", "", ReadmeText);
        zip.Save(Response.OutputStream);
    }
    // Response.End();  // no! See https://dev59.com/B3NA5IYBdhLWcg3wHp-B
    Response.Close();

DotNetZip是免费的。


17

现在您不必再使用外部库了。System.IO.Packaging有可以用来将内容放入zip文件的类。然而,这并不简单。这里有一篇博客文章,其中包含一个示例(在末尾找到它)。


链接不稳定,因此这里是Jon在帖子中提供的示例。
using System;
using System.IO;
using System.IO.Packaging;

namespace ZipSample
{
    class Program
    {
        static void Main(string[] args)
        {
            AddFileToZip("Output.zip", @"C:\Windows\Notepad.exe");
            AddFileToZip("Output.zip", @"C:\Windows\System32\Calc.exe");
        }

        private const long BUFFER_SIZE = 4096;

        private static void AddFileToZip(string zipFilename, string fileToAdd)
        {
            using (Package zip = System.IO.Packaging.Package.Open(zipFilename, FileMode.OpenOrCreate))
            {
                string destFilename = ".\\" + Path.GetFileName(fileToAdd);
                Uri uri = PackUriHelper.CreatePartUri(new Uri(destFilename, UriKind.Relative));
                if (zip.PartExists(uri))
                {
                    zip.DeletePart(uri);
                }
                PackagePart part = zip.CreatePart(uri, "",CompressionOption.Normal);
                using (FileStream fileStream = new FileStream(fileToAdd, FileMode.Open, FileAccess.Read))
                {
                    using (Stream dest = part.GetStream())
                    {
                        CopyStream(fileStream, dest);
                    }
                }
            }
        }

        private static void CopyStream(System.IO.FileStream inputStream, System.IO.Stream outputStream)
        {
            long bufferSize = inputStream.Length < BUFFER_SIZE ? inputStream.Length : BUFFER_SIZE;
            byte[] buffer = new byte[bufferSize];
            int bytesRead = 0;
            long bytesWritten = 0;
            while ((bytesRead = inputStream.Read(buffer, 0, buffer.Length)) != 0)
            {
                outputStream.Write(buffer, 0, bytesRead);
                bytesWritten += bytesRead;
            }
        }
    }
}

非常感谢作者保持更新的超级有用的链接! - Jeff Sternal
请查看此链接:http://weblogs.asp.net/dneimke/archive/2005/02/25/380273.aspx - daitangio
@BernhardPoiss 这就是为什么SO不再允许仅链接答案的原因。我无法自行删除,因为它已被选中。我已经修复了链接,并将VTC此问题作为一个类似问题的重复,实际上在答案中有代码。编辑好吧,没有金徽章,所以没有重复锤。我只需编辑代码片段即可。 - user1228

10
如果您使用的是.NET Framework 4.5或更高版本,您可以避免使用第三方库,而是使用本机类System.IO.Compression.ZipArchive
以下是一个使用MemoryStream和代表两个文件的字节数组的快速代码示例:
byte[] file1 = GetFile1ByteArray();
byte[] file2 = GetFile2ByteArray();

using (MemoryStream ms = new MemoryStream())
{
    using (var archive = new ZipArchive(ms, ZipArchiveMode.Create, true))
    {
        var zipArchiveEntry = archive.CreateEntry("file1.txt", CompressionLevel.Fastest);
        using (var zipStream = zipArchiveEntry.Open()) zipStream.Write(file1, 0, file1.Length);
        zipArchiveEntry = archive.CreateEntry("file2.txt", CompressionLevel.Fastest);
        using (var zipStream = zipArchiveEntry.Open()) zipStream.Write(file2, 0, file2.Length);
    }
    return File(ms.ToArray(), "application/zip", "Archive.zip");
}

你可以在MVC控制器中使用它来返回一个ActionResult,或者如果需要实际创建zip归档文件,则可以将MemoryStream持久化到磁盘,或者完全用FileStream替换它。
关于此主题的更多信息,您还可以在我的博客上阅读这篇文章

3
这是最好的和最简单的答案! - VDWWD
1
最佳答案在这里。请注意,尽管我的项目针对4.8版本,但我仍然需要从NuGet获取System.IO.Compression.ZipFile,否则就不存在对ZipArchive的引用。 - EvilDr

7

3

1

可以使用DotNetZip来完成此操作。您可以从Visual Studio Nuget包管理器或直接通过DotnetZip下载它。 然后尝试下面的代码:

     /// <summary>
    /// Generate zip file and save it into given location
    /// </summary>
    /// <param name="directoryPath"></param>
    public void CreateZipFile(string directoryPath )
    {
        //Select Files from given directory
        List<string> directoryFileNames = Directory.GetFiles(directoryPath).ToList();
        using (ZipFile zip = new ZipFile())
        {
            zip.AddFiles(directoryFileNames, "");
            //Generate zip file folder into loation
            zip.Save("C:\\Logs\\ReportsMyZipFile.zip");
        }
    }

如果您想将文件下载到客户端,请使用以下代码。
/// <summary>
    /// Generate zip file and download into client
    /// </summary>
    /// <param name="directoryPath"></param>
    /// <param name="respnse"></param>
    public void CreateZipFile(HttpResponse respnse,string directoryPath )
    {
        //Select Files from given directory
        List<string> directoryFileNames = Directory.GetFiles(directoryPath).ToList();
        respnse.Clear();
        respnse.BufferOutput = false;
        respnse.ContentType = "application/zip";
        respnse.AddHeader("content-disposition", "attachment; filename=MyFiles.zip");

        using (ZipFile zip = new ZipFile())
        {
            zip.CompressionLevel = CompressionLevel.None;
            zip.AddFiles(directoryFileNames, "");
            zip.Save(respnse.OutputStream);
        }

        respnse.flush();
    }

1

我们公司也使用了这个组件。由于组件中的错误,一些极度紧张的服务引发了EngineException异常。在与微软支持的沟通后,我们决定转向SharpZLib。这是两年前的事情了。我不知道这个组件今天的表现如何? - Michael Piendl
我们从未遇到过任何问题,但它通常用于每小时运行一次的导出服务,但通常是每天。加密也非常有用。 - Macros

0

通过我们的Rebex ZIP组件,可以“即时”创建ZIP文件。

以下示例完整描述了此过程,包括创建子文件夹:

// prepare MemoryStream to create ZIP archive within
using (MemoryStream ms = new MemoryStream())
{
    // create new ZIP archive within prepared MemoryStream
    using (ZipArchive zip = new ZipArchive(ms))
    {            
         // add some files to ZIP archive
         zip.Add(@"c:\temp\testfile.txt");
         zip.Add(@"c:\temp\innerfile.txt", @"\subfolder");

         // clear response stream and set the response header and content type
         Response.Clear();
         Response.ContentType = "application/zip";
         Response.AddHeader("content-disposition", "filename=sample.zip");

         // write content of the MemoryStream (created ZIP archive) to the response stream
         ms.WriteTo(Response.OutputStream);
    }
}

// close the current HTTP response and stop executing this page
HttpContext.Current.ApplicationInstance.CompleteRequest();

0
#region Create zip file in asp.net c#
        string DocPath1 = null;/*This varialble is Used for Craetting  the File path .*/
        DocPath1 = Server.MapPath("~/MYPDF/") + ddlCode.SelectedValue + "/" + txtYear.Value + "/" + ddlMonth.SelectedValue + "/";
        string[] Filenames1 = Directory.GetFiles(DocPath1);
        using (ZipFile zip = new ZipFile())
        {
            zip.AddFiles(Filenames, "Pdf");//Zip file inside filename
            Response.Clear();
            Response.BufferOutput = false;
            string zipName = String.Format("Zip_{0}.zip", DateTime.Now.ToString("yyyy-MMM-dd-HHmmss"));
            Response.ContentType = "application/zip";
            Response.AddHeader("content-disposition", "attachment; filename=" + zipName);
            zip.Save(Response.OutputStream);
            Response.End();
        }
        #endregion

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接