Search code examples
asp.net-web-apihttpcontent

Web API - Setting Response.Content with byte[] / MemoryStream Contents not working properly


My requirement is to use Web API to send across the network, a zip file (consisting a bunch of files in turn) which should not be written anywhere locally (not written anywhere on the server/client disk). For zipping, I am using DotNetZip - Ionic.Zip.dll

Code at Server:

public async Task<IHttpActionResult> GenerateZip(Dictionary<string, StringBuilder> fileList)
    { 
// fileList is actually a dictionary of “FileName”,”FileContent”
        byte[] data;
        using (ZipFile zip = new ZipFile())
        {
            foreach (var item in filelist.ToArray())
            {
                zip.AddEntry(item.Key, item.Value.ToString());
            }

            using (MemoryStream ms = new MemoryStream())
            {
                zip.Save(ms);
                data = ms.ToArray();
            }            
        }

        var result = new HttpResponseMessage(HttpStatusCode.OK);
        MemoryStream streams = new MemoryStream(data);
        //, 0, data.Length-1, true, false);
        streams.Position = 0;

        //Encoding UTFEncode = new UTF8Encoding();
        //string res = UTFEncode.GetString(data);
        //result.Content = new StringContent(res, Encoding.UTF8, "application/zip");
        <result.Content = new StreamContent(streams);
        result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/zip");
        //result.Content.Headers.ContentLength = data.Length;
        result.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment");
        result.Content.Headers.ContentDisposition.FileName = "test.zip";
        return this.Ok(result);
    }

The issue I am facing is that after the zip file downloaded at client end when modified as a test.bin has its stream contents (byte[] data in this example’s contents) missing. (I am getting back a test.zip file. When I change the file locally from test.zip to test.bin, I am seeing that the File’s contents as shown below. It does not contain the Response.Content values. P.S. I have also tried the MIME type “application/octet-stream” as well. No luck!)

Test.zip aka test.bin’s contents:

{"version":{"major":1,"minor":1,"build":-1,"revision":-1,"majorRevision":-1,"minorRevision":-1},
"content":{"headers":[{"key":"Content-Type","value":["application/zip"]},
{"key":"Content-Disposition","value":["attachment; filename=test.zip"]}]},
"statusCode":200,"reasonPhrase":"OK","headers":[],"isSuccessStatusCode":true}

Can someone please help me on how we can set result.Content with a MemoryStream object (I have seen example of “FileStream” at other places on google to set “result.Content” but I want to use MemoryStream object only!). I am highlighting this because I think the problem lies with setting the MemoryStream object to the result.Content (in order to properly save the streams content into the result.Content object)

P.S. I have also gone thru Uploading/Downloading Byte Arrays with AngularJS and ASP.NET Web API (and a bunch of other links) but it did not help me much… :( Any help is greatly appreciated. Thanks a lot in advance :)


Solution

  • I got my issue solved!!

    All I did was to change the Response Type to HttpResponseMessage and use "return result" in the last line rather than Ok(result) { i.e. HttpResponseMessage Type rather than OKNegiotatedContentResult Type)