Search code examples
asp.net.netasp.net-web-apiazure-blob-storagesharpziplib

Zip Azure Storage Files and Return File from Web API returns corrupted files when unzipped


Zip Azure Storage Files and Return File from Web API returns corrupted files when unzipped. Here is my code:

[HttpPost(nameof(DownloadFiles))]
public async Task<IActionResult> DownloadFiles(List<string> fileNames)
{

    CloudBlockBlob blockBlob;
    MemoryStream outputMemStream = new MemoryStream();
    ZipOutputStream zipStream = new ZipOutputStream(outputMemStream);
    Stream blobStream;
    zipStream.SetLevel(3); //0-9, 9 being the highest level of compression

    string blobstorageconnection = _configuration.GetValue<string>("BlobConnectionString");
    CloudStorageAccount cloudStorageAccount = CloudStorageAccount.Parse(blobstorageconnection);
    CloudBlobClient cloudBlobClient = cloudStorageAccount.CreateCloudBlobClient();
    CloudBlobContainer cloudBlobContainer = cloudBlobClient.GetContainerReference(_configuration.GetValue<string>("BlobContainerName"));

    using (MemoryStream memoryStream = new MemoryStream())
    {
        foreach (string fileName in fileNames)
        {
            blockBlob = cloudBlobContainer.GetBlockBlobReference(fileName);
            await blockBlob.DownloadToStreamAsync(memoryStream);

            ZipEntry newEntry = new ZipEntry(blockBlob.Name);
            newEntry.DateTime = DateTime.Now;

            zipStream.PutNextEntry(newEntry);

            StreamUtils.Copy(memoryStream, zipStream, new byte[4096]);
            zipStream.CloseEntry();
        }
    };

    zipStream.IsStreamOwner = false;    // False stops the Close also Closing the underlying stream.
    zipStream.Close();                  // Must finish the ZipOutputStream before using outputMemStream.

    outputMemStream.Position = 0;

    HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK);
    result.Content = new StreamContent(outputMemStream);
    result.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment");
    result.Content.Headers.ContentDisposition.FileName = "Documents.zip";
    result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
    result.Content.Headers.ContentLength = outputMemStream.Length;
    return File(outputMemStream, "application/octet-stream", "Documents.zip");
}

I am using SharpZipLib, and when I download the Zipped file and unzip it, the files contained in this file are corrupted.

Any advice?

I was trying to zip files on my azure storage to download them as a zip, but the files in the downloaded zip are corrupted


Solution

  • [HttpPost(nameof(DownloadFiles))]
        public async Task<IActionResult> DownloadFiles(List<string> fileNames)
        {
            MemoryStream outputMemStream = new MemoryStream();
            ZipOutputStream zipStream = new ZipOutputStream(outputMemStream);
    
            zipStream.SetLevel(3); //0-9, 9 being the highest level of compression
            byte[] bytes = null;
    
            foreach (string fileName in fileNames)
            {
                var newEntry = new ZipEntry(fileName);
                newEntry.DateTime = DateTime.Now;
    
                zipStream.PutNextEntry(newEntry);
    
                bytes = await CreateFile(fileName);
    
                MemoryStream inStream = new MemoryStream(bytes);
                StreamUtils.Copy(inStream, zipStream, new byte[4096]);
                inStream.Close();
                zipStream.CloseEntry();
            }
    
            zipStream.IsStreamOwner = false;    // False stops the Close also Closing the underlying stream.
            zipStream.Close();          // Must finish the ZipOutputStream before using outputMemStream.
    
            outputMemStream.Position = 0;
    
            return File(outputMemStream.ToArray(), "application/octet-stream", "directory.zip");
        }
        private async Task<byte[]> CreateFile(string fileName)
        {
            byte[] bytes = null;
            await using (MemoryStream ms = new MemoryStream())
            {
                CloudBlockBlob blockBlob;
                string blobstorageconnection = _configuration.GetValue<string>("BlobConnectionString");
                CloudStorageAccount cloudStorageAccount = CloudStorageAccount.Parse(blobstorageconnection);
                CloudBlobClient cloudBlobClient = cloudStorageAccount.CreateCloudBlobClient();
                CloudBlobContainer cloudBlobContainer = cloudBlobClient.GetContainerReference(_configuration.GetValue<string>("BlobContainerName"));
                blockBlob = cloudBlobContainer.GetBlockBlobReference(fileName);
                await blockBlob.DownloadToStreamAsync(ms);
                bytes = ms.ToArray();
            }
    
            return bytes;
        }