27

Need to dynamically package some files into a .zip to create a SCORM package, anyone know how this can be done using code? Is it possible to build the folder structure dynamically inside of the .zip as well?

MetaGuru
  • 42,847
  • 67
  • 188
  • 294
  • Possible duplicate of [Using System.IO.Packaging to generate a ZIP file](http://stackoverflow.com/questions/6386113/using-system-io-packaging-to-generate-a-zip-file) –  Jan 14 '16 at 19:24

9 Answers9

22

DotNetZip is nice for this.

You can write the zip directly to the Response.OutputStream. The code looks like this:

    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 http://stackoverflow.com/questions/1087777
    Response.Close();

DotNetZip is free.

Phill
  • 18,398
  • 7
  • 62
  • 102
Cheeso
  • 189,189
  • 101
  • 473
  • 713
17

You don't have to use an external library anymore. System.IO.Packaging has classes that can be used to drop content into a zip file. Its not simple, however. Here's a blog post with an example (its at the end; dig for it).


The link isn't stable, so here's the example Jon provided in the post.

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;
            }
        }
    }
}
  • +1 for the extremely useful link that the author is keeping up to date. – Jeff Sternal Jul 06 '09 at 15:59
  • Take also a look to this link http://weblogs.asp.net/dneimke/archive/2005/02/25/380273.aspx – daitangio Feb 01 '11 at 13:46
  • @BernhardPoiss And that's why SO doesn't allow link-only answers anymore. I can't self-delete as it's selected. I've fixed the link, and I'm going to VTC this question as a dupe of a similar that actually has the code in the answer. ***edit*** well, no gold badge, so no dupehammer. I'll just edit in the code snip. –  Jan 14 '16 at 19:24
10

If you're using .NET Framework 4.5 or newer you can avoid third-party libraries and use the System.IO.Compression.ZipArchive native class.

Here’s a quick code sample using a MemoryStream and a couple of byte arrays representing two files:

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");
}

You can use it inside a MVC Controller returning an ActionResult: alternatively, if you need to phisically create the zip archive, you can either persist the MemoryStream to disk or entirely replace it with a FileStream.

For further info regarding this topic you can also read this post on my blog.

Darkseal
  • 9,205
  • 8
  • 78
  • 111
  • 3
    This is the best and simplest answer! – VDWWD Oct 26 '20 at 14:48
  • 1
    Best answer here. Note that despite having a project targeting 4.8, I still had to get `System.IO.Compression.ZipFile` from NuGet otherwise a reference to ZipArchive didn't exist. – EvilDr Jul 13 '21 at 10:23
7

You could take a look at SharpZipLib. And here's a sample.

Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
3

DotNetZip is very easy to use... Creating Zip files in ASP.Net

Bala
  • 31
  • 1
1

Able to do this using DotNetZip. you can download it from the visual studio Nuget package manger or directly via the DotnetZip. then try below code,

     /// <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");
        }
    }

If you want to download the file into client,use below code.

/// <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();
    }
Hasiya
  • 1,298
  • 1
  • 7
  • 7
1

I have used a free component from chilkat for this: http://www.chilkatsoft.com/zip-dotnet.asp. Does pretty much everything I have needed however I am not sure about building the file structure dynamically.

Macros
  • 7,099
  • 2
  • 39
  • 61
  • We used this component in our company too. Based on errors in the component some of our extremly stressed services caused an EngineException. After an Microsoft Support Ticket we decided to switch to SharpZLib. This was 2 years ago. I do not know how good the component is today? – Michael Piendl Mar 25 '09 at 15:00
  • We've never had any problems with it however is used in export services which generally run at the most every hour, but typically daily. The encryption is useful as well – Macros Mar 25 '09 at 16:58
0

Creating ZIP file "on the fly" would be done using our Rebex ZIP component.

The following sample describes it fully, including creating a subfolder:

// 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();
Jan Šotola
  • 842
  • 8
  • 25
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
Code
  • 679
  • 5
  • 9