Use SharpZipLIb to create zip file directly from database without saving any temporary files on the hard disk

by jasonvonruden 28. July 2010 00:13

The Goal

I needed to package up inspection photos into a zip file and make them available for download directly from a website.   The inspection photos are stored not stored in the file system, instead they are stored in a MySql database via NHibernate. 

My Approach

Every example that I could find involved reading the database, writing out the files to a temporary working directory on the hard disk,  zip up the files using SharpZipLib, and then delete the temporary files.  

This seemed like a lot of extra work!

So I decided to create my zip file completely in-memory and skip writing out the files to working directory on disk.

Steps:

  1. Determine if inspection has any photo attachments.
  2. Create Zip File Memory Streams using SharpZipLib a .NET compression library that supports Zip files using both stored and deflate compression methods, PKZIP 2.0 style and AES encryption, tar with GNU long filename extensions, gzip, zlib and raw deflate, as well as BZip2.
  3. Read every photo on the database and create zip entries in memory streams.
  4. Finalize the zip file.
  5. Return the zip file to the user via website http response stream.

Generate Inspection Photo Zip File

//*****************************************************************************
//Generate Inspection Photo Zip File
//*****************************************************************************
public byte[] GenerateInspectionPhotosZipFile(Inspection _inspection)
{
    //Open Zip File.
    MemoryStream zipOutMemoryStream = new MemoryStream();
    ZipOutputStream zipOutStream = new ZipOutputStream(zipOutMemoryStream);
 
    //Add Photos to Zip File.
    foreach (var inspectionAttachment in _inspection.fkInspectionAttachments)
    {
        if (inspectionAttachment.Attachment != null && inspectionAttachment.Attachment.Length > 0)
        {
            MemoryStream photoMemoryStream = new MemoryStream(inspectionAttachment.Attachment);
            ZipEntry entry = new ZipEntry(inspectionAttachment.AttachmentName);
            zipOutStream.PutNextEntry(entry);
            byte[] photoBytesBuffer = photoMemoryStream.ToArray();
            zipOutStream.Write(photoBytesBuffer, 0, photoBytesBuffer.Length);
            photoMemoryStream.Dispose();
            zipOutStream.CloseEntry();
        }
    }
    zipOutStream.Finish();
    zipOutStream.Close();
    zipOutMemoryStream.Close();
    byte[] responseBytes = zipOutMemoryStream.ToArray();
    zipOutMemoryStream.Dispose();
    zipOutStream.Dispose();
 
    //Return Null on Empty Zip File
    const int ZIP_FILE_EMPTY = 22;
    if (responseBytes.Length <= ZIP_FILE_EMPTY)
        return null;
 
    return responseBytes;
}

Return Photo to User Via Http Output Response Stream

//*****************************************************************************
 //Build Inspection Photo Zip File
 //*****************************************************************************
 private void GenerateInspectionPhotosZipFile(NHibernateDataProvider _provider, Inspection _inspection)
 {
     //Generate Inspection Photos.
     byte[] responseBytes = _provider.GenerateInspectionPhotosZipFile(_inspection);
 
     //Return Zipfile in Response Output Stream
     if (responseBytes != null)
     {
         //Response Return Zip File
         Response.ContentType = "application/zip";
         Response.AppendHeader("Content-Disposition", string.Format("attachment; filename=InspectionPhotos_{0}_{1}_{2}.zip", _inspection.Id.Inspectionid, _inspection.Bankid, _inspection.Processorid));
         Response.OutputStream.Write(responseBytes, 0, responseBytes.Length);
     }
 }

Tags:

c# | NHibernate