Tom el Safadi
Tom el Safadi

Reputation: 6786

Zip Azure Storage Files and Return File from Web Api

I am trying to create a zip file with SharpZipLib from files stored on Azure Storage. Unfortunately I am not able to return them because the Api always returns a Json:

{"Version":{"Major":1,"Minor":1,"Build":-1,"Revision":-1,"MajorRevision":-1,"MinorRevision":-1},"Content":{"Headers":[{"Key":"Content-Disposition","Value":["attachment; filename=Documents.zip"]},{"Key":"Content-Type","Value":["application/octet-stream"]},{"Key":"Content-Length","Value":["498"]}]},"StatusCode":200,"ReasonPhrase":"OK","Headers":[],"RequestMessage":null,"IsSuccessStatusCode":true}

The zipping should work which I use, however I am not sure if everything is correct since I was never able to see the file.

This is the code for zipping the files and returning the zip file:

[HttpGet("DownloadFiles")]
public async Task<HttpResponseMessage> DownloadFiles(string invoiceNr, List<string> fileNames)
{
    List<CloudBlockBlob> blobs = _documentService.GetBlobs(invoiceNr, fileNames);

    MemoryStream outputMemStream = new MemoryStream();
    ZipOutputStream zipStream = new ZipOutputStream(outputMemStream);

    zipStream.SetLevel(3); //0-9, 9 being the highest level of compression

    foreach (CloudBlockBlob blob in blobs)
    {
        using (MemoryStream blobStream = new MemoryStream())
        {
            await blob.DownloadToStreamAsync(blobStream);

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

            zipStream.PutNextEntry(newEntry);

            StreamUtils.Copy(blobStream, 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 result;
}

Is it the wrong way of returning a file from WebAPi? Am I doing something wrong in general?

Thanks in advance for the help.

Upvotes: 1

Views: 1093

Answers (1)

Yuriy Gavrishov
Yuriy Gavrishov

Reputation: 5021

As you declare your web method as

public async Task<HttpResponseMessage> DownloadFiles(...)

ASP.NET Core treats HttpResponseMessage as model and your methods returns instance of this file serialized as JSON. The correct version of this method is

public async Task<IActionResult> DownloadFiles()
{
    ...
    return File(outputMemStream, "application/octet-stream", "Documents.zip");
}

Upvotes: 2

Related Questions