Working With Zip Files In ASP.NET MVC

5 (4 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: 1597

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

Cyrus 16/05/2017 19:55
In response to Razor Pages - Getting Started With The Preview
There is something wrong related to microsoft.dotnetcore.mvc.taghelpers! if you remove it from page...

Cyrus 16/05/2017 10:18
In response to Razor Pages - Getting Started With The Preview
well done mike, it was very useful, I really appreciate that....

Satyabrata Mohapatra 16/05/2017 07:21
In response to Razor Pages - Getting Started With The Preview
Finally!!!! web pages in asp.net core!!! Super excited !!!! Thank u sir for sharing.....Awaiting on...

Daniele 14/03/2017 10:24
In response to Working With Zip Files In ASP.NET MVC
is it possible give to the user a progress bar of the zipping process? Thanks in advance. ...

Suraj 13/03/2017 22:20
In response to Working With Zip Files In ASP.NET MVC
Very nice article. Thanks....

Satyabrata Mohapatra 19/02/2017 03:01
In response to Free SSL Certificates On IIS With LetsEncrypt
Thanks for sharing. Learned a lot !!...

Gfw 03/02/2017 09:48
In response to Free SSL Certificates On IIS With LetsEncrypt
I have used WinSimple for about the last 9 months - works great. One thing that you want to make of...

Ted Driver 02/02/2017 13:24
In response to Free SSL Certificates On IIS With LetsEncrypt
This looks great is you have command line access to your web server - what about those of us on Is...

Aghil 16/11/2016 18:16
In response to Server.MapPath Equivalent in ASP.NET Core
Hi, Thanks, it was really good. However, how can we access the in the Classes? Is there any...

Carl T. 06/11/2016 05:43
In response to Server.MapPath Equivalent in ASP.NET Core
Very succinct and easy to follow. Worked perfectly the first time for me. Thanks!!...