0

I'm zipping multiple files via a Web API endpoint which I then download to my browser. Until the very last step, I can see that the zip file has a filename and that its size is set but for some reason, when downloaded, it comes back as a 1Kb file.

I've saved the binary array that contains the zip file to my local drive before returning it back to the browser via the Web API and it is indeed correct. I can open the zip file and see its content, so I'm not sure what's causing it the problem.

Clearly not the zipping since I can save it locally and it is correct, so I can only assume it has must be something with the EndPoint, but what? I use a custom IHttpActionResult:

public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
{
    HttpResponseMessage response = new HttpResponseMessage();

    var filename = this.Document.GetFilename();

    var mimeType = MimeMapping.GetMimeMapping(filename);
    response.Content = new StreamContent(new MemoryStream(this.Document.ToData()));
    response.Content.Headers.ContentLength = this.Document.Data.Length;
    response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
    {
        FileName = filename
    };
    response.Content.Headers.ContentType = new MediaTypeHeaderValue(mimeType);

    return Task.FromResult(response);
}

and it looks fine to me and the odd thing is that if I download a document such as MS Word or other, it download just fine using custom IHttpActionResult and same endpoint.

To download the file via the Web API and JQuery, I found the following article:

DOWNLOAD FILE WITH JQUERY AND WEB API 2.0 IHTTPACTIONRESULT

Could it be that the saving of the blob occurs before the file is fully downloaded but then why does it work for other files?

If you want me to provide any other code, let me know but if anyone has any suggestions that would be great.

Thanks.

UPDATE-1:

Unlike previously stated, my single file download such as MS Word no longer work either and also generate a 1kb file instead of the relevant file. Something has changed but I'm not sure what yet. I will post an update when I find out.

Thierry
  • 6,142
  • 13
  • 66
  • 117
  • Is `this.Document.Data.Length` giving the correct value? –  Apr 12 '21 at 17:25
  • @amy As far as I can tell, it is. I have corrected my question as I just noticed that I stated that it worked for the likes of MS word and my problem was just with Zip files but this is not the case. The problem is with all files so I must have changed something as I originally got it to work when I was only dealing with single file download but I'm not sure what. I'll see if I can spot anything. I will update my question not to cause confusion and hopefully, I'll figure out what has changed and post an update. Really odd that when the length is set, it is definitely a value greater than 1k. – Thierry Apr 12 '21 at 22:59

1 Answers1

0

I have fixed the problem by using the code provided directly provided from:

Handle file download from ajax post

from @JonathanAmend (All kudos to him!!)

success: function(blob, status, xhr) {
    // check for a filename
    var filename = "";
    var disposition = xhr.getResponseHeader('Content-Disposition');
    if (disposition && disposition.indexOf('attachment') !== -1) {
        var filenameRegex = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/;
        var matches = filenameRegex.exec(disposition);
        if (matches != null && matches[1]) filename = matches[1].replace(/['"]/g, '');
    }

    if (typeof window.navigator.msSaveBlob !== 'undefined') {
        // IE workaround for "HTML7007: One or more blob URLs were revoked by closing the blob for which they were created. These URLs will no longer resolve as the data backing the URL has been freed."
        window.navigator.msSaveBlob(blob, filename);
    } else {
        var URL = window.URL || window.webkitURL;
        var downloadUrl = URL.createObjectURL(blob);

        if (filename) {
            // use HTML5 a[download] attribute to specify filename
            var a = document.createElement("a");
            // safari doesn't support this yet
            if (typeof a.download === 'undefined') {
                window.location.href = downloadUrl;
            } else {
                a.href = downloadUrl;
                a.download = filename;
                document.body.appendChild(a);
                a.click();
            }
        } else {
            window.location.href = downloadUrl;
        }

        setTimeout(function () { URL.revokeObjectURL(downloadUrl); }, 100); // cleanup
    }

Some subtle differences:

  1. I had my code in the completed promise rather than the success

  2. I didn't have the following code in my ajax request

    xhrFields: { // to avoid binary data being mangled on charset conversion responseType: 'blob' },

  3. There are not minor differences between his code and the one I found in DOWNLOAD FILE WITH JQUERY AND WEB API 2.0 IHTTPACTIONRESULT as provided in the original question but I don't have time right now to compare the 2. I'll try to do this over the weekend and update my answer but from what I've seen so far, it doesn't seem likely that the differences caused the problem.

Thierry
  • 6,142
  • 13
  • 66
  • 117