Working With Zip Files In ASP.NET MVC

5 (5 votes)

Since ASP.NET 4.5, zipping and unzipping files can be done with classes from within the .NET framework. Despite that, nearly all examples that illustrate working with zip files in ASP.NET applications feature third party open source compression libraries. This short article attempts to correct that by demonstrating the use of the System.IO.Compression classes to unpack an uploaded zip file, and to create one for download in an ASP.NET MVC application.

Unpacking an uploaded zip file

To begin, you need to add a reference to System.IO.Compression to your project. Having done that, here is an upload form for the zip file:

@using (Html.BeginForm("Index", "Home", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
    <input type="file" name="zip"  /> 
    <div>
        <button class="btn btn-default">Submit</button>
    </div>
}

Note that the form's method is specified as POST and that the enctype attribute is set with a value of multipart/form-data - both prerequisites for being able to upload files. The form is posted to the following controller action:

[HttpPost]
public ActionResult Index(HttpPostedFileBase zip)
{
    var uploads = Server.MapPath("~/uploads");
    using (ZipArchive archive = new ZipArchive(zip.InputStream))
    {
        foreach (ZipArchiveEntry entry in archive.Entries)
        {
            if (!string.IsNullOrEmpty(Path.GetExtension(entry.FullName))) //make sure it's not a folder
            {
                entry.ExtractToFile(Path.Combine(uploads, entry.FullName));
            }
            else
            {
                Directory.CreateDirectory(Path.Combine(uploads, entry.FullName));
            }
        }
    }
    ViewBag.Files = Directory.EnumerateFiles(uploads);
    return View();
}

The action's parameter is an HttpPostedFileBase named after the name attribute of the file upload control in the form. The code creates an instance of the ZipArchive class from the content of the uploaded file and then iterates the contents of the archive. If the name of an entry has a file extension, it is a file. If not, it is a folder. The code will save the extracted file or create a folder accordingly.

Creating a Zip file for download

The simple example that follows illustrates the use of the static ZipFile.CreateFromDirectory method which, despite the fact that it is in the System.IO.Compression namespace , actually resides in the System.IO.Compression.FileSystem assembly, so you need to add a reference to that in your controller. The user is presented with a list of checkboxes representing a selection of files to choose from. Submitting the form will result in just those files being packaged up into one zip file and downloaded.

The list of files is passed to the view via ViewBag:

public ActionResult Index()
{
    ViewBag.Files = Directory.EnumerateFiles(Server.MapPath("~/pdfs"));
    return View();
}

The files are listed within a form with a set of checkboxes:

<h2>Select downloads</h2>
@using(Html.BeginForm("Download", "Home"))
{
    foreach(string file in ViewBag.Files)
    {
        <input type="checkbox" name="files" value="@file" /> @:&nbsp;  
             @Path.GetFileNameWithoutExtension(file) <br />
    }
    <div>
        <button class="btn btn-default">Submit</button>
    </div>
}

The form posts to an action called Download which consists of the following code:

[HttpPost]
public FileResult Download(List<string> files)
{
    var archive = Server.MapPath("~/archive.zip");
    var temp = Server.MapPath("~/temp");

    // clear any existing archive
    if (System.IO.File.Exists(archive))
    {
        System.IO.File.Delete(archive);
    }
    // empty the temp folder
    Directory.EnumerateFiles(temp).ToList().ForEach(f => System.IO.File.Delete(f));

    // copy the selected files to the temp folder
    files.ForEach(f => System.IO.File.Copy(f, Path.Combine(temp, Path.GetFileName(f))));

    // create a new archive
    ZipFile.CreateFromDirectory(temp, archive);

    return File(archive, "application/zip", "archive.zip");
}

The user selection is captured in the files parameter. The code checks to see if a file called archive.zip exists from previous operations and it it does, it is deleted. Then a folder called temp is cleared of any existing files. Next,the selected files are copied from their source directory to the temp folder. The ZipFile.CreateFromDirectory method generates a zip file from the temp directory contents and saves it as archive.zip. Finally, it is written to the Response.

Both of these examples are simplified to illustrate the main classes and methods required to perform the tasks as clearly as possible. When handling the upload, you should add validation to check that the uploaded file is in fact a zip file, for example. Also, the zip file that gets created is placed into a hardcoded folder. If you have a busy site where multiple users are downloading zip files at the same time, you may want to use a Guid as a folder name instead to avoid the possibility of one user's download overwriting another.

You might also like...

Date Posted:
Last Updated:
Posted by:
Total Views to date: 5406

2 Comments

- Suraj

Very nice article. Thanks.

- Daniele

is it possible give to the user a progress bar of the zipping process?
Thanks in advance.

Recent Comments

Pam 30/08/2017 11:30
In response to Sending Email in Razor Pages
Mike, RazorPages sound like a nice choice for somebody still working in ASP classic who wants to to...

Robby Robson 15/08/2017 00:43
In response to Routing in Razor Pages
Mike: great stuff. Now that .Core Standard 2.0 is formally out, how soon will you rewrite your book...

Satyabrata Mohapatra 28/07/2017 08:59
In response to Sending Email in Razor Pages
Bit off topic, but congratulation sir for your MVP award. You deserve it !!!...

Satyabrata Mohapatra 23/07/2017 16:43
In response to Razor Pages - The Elevator Pitch
@Dale Severin You can continue to build apps using asp.net web pages....

Satyabrata Mohapatra 23/07/2017 16:40
In response to Sending Email in Razor Pages
Thanks for sharing...learned a lot...

Gfw 22/07/2017 11:53
In response to Sending Email in Razor Pages
Question... Does System.Net.Mail support SSL?...

Dale Severin 20/07/2017 03:38
In response to Razor Pages - The Elevator Pitch
I work with razor web pages extensively. I appreciate the rapid development it permits me to I am as...

Obinna Okafor 14/07/2017 01:19
In response to Routing in Razor Pages
Thank you, Mike. Good post....

Satyabrata Mohapatra 11/07/2017 16:02
In response to Routing in Razor Pages
Very powerful routing system!!...

Cyrus 05/07/2017 03:41
In response to Razor Pages - Getting Started With The Preview
How can I trim packages and services as much as possible to use just razor pages? I don’t want to to...