Search code examples
javascriptc#encodingaxioszip

Download ANSI zip file in front end, generated by C# back end


I have a C# backend generating a zip file in memory (with System.IO.Compression) and sending it to my front end. If I download the zip file before sending it, it is working well and is in ANSI encoding (found on notepad++).

This is how I return my file currently, I have tried many different ways to do it, such as simply returning a file without headers, but right now it looks like this :

[HttpPost]
[Route("GetUserWorkContext")]
public async Task<IActionResult> GetUserWorkContext([FromBody] GetUserWorkContextRequest request, [FromServices] IExportManager exportManager)
{
    var zipStream = await exportManager.GetUserWorkContext(userId, request.IncludeArchived);
    HttpContext.Response.Headers.Add("Content-Disposition", "attachment; filename = test.zip; charset=Windows-1252");
    HttpContext.Response.Headers.Add("Content-Length", zipStream.ToArray().Length.ToString());
    return File(zipStream.ToArray(), "application/octet-stream");
}

It seems that no matter how I download the file with Javascript (front-end), it is saved with utf8 encoding (found with notepad++ again). I tried using js-file-download ( https://www.npmjs.com/package/js-file-download ) or creating blobs, but anything I end up downloading is encoded in utf8.

How should I go about downloading this file in Javascript without corrupting the archive ?

Here is my current attempt in Javascript, using a piece of code I found here (JavaScript blob filename without link) to download the file :

function getUserWorkContext({ includeArchived }) {
    return new Promise(function () {
        Axios.post('/api/Export/GetUserWorkContext', {includeArchived})
            .then((response) => {
                if(response.data){
                    var blobObject = new Blob([response.data], {type: 'application/zip;charset=Windows-1252'});
                    downloadFile(blobObject, "test.zip");
                }
            })
}

function downloadFile(file, fileName) {
    if (navigator.msSaveBlob) { // For ie and Edge
        return navigator.msSaveBlob(file, fileName);
    }
    else {
        let link = document.createElement('a');
        link.href = window.URL.createObjectURL(file);
        link.download = fileName;
        document.body.appendChild(link);
        link.dispatchEvent(new MouseEvent('click', { bubbles: true, cancelable: true, view: window }));
        link.remove();
        window.URL.revokeObjectURL(link.href);
    }
}

Note : the actual zip is 3,747KB where as the download zip from Javascript is always much bigger, in this case : 6,917KB.


Solution

  • This is a problem with axios:

    I guess, you should use blob or arraybuffer as responseType for axios.

    { responseType: 'blob' }
    

    // responseType indicates the type of data that the server will respond with // options are: 'arraybuffer', 'document', 'json', 'text', 'stream' // browser only: 'blob'

    responseType: 'json' // default

    Check this answer: https://stackoverflow.com/a/60461828/2487565

    === 8< ======================= previous version ======================= 8< ===

    Your Content-Disposition header is wrong. There is no charset parameter for Content-Disposition header.

    Check the docs: MDN HTTP Content-Disposition

    That's why your file is still sent in UTF-8, since your charset parameter has no effect.

    To use UTF-8:

    Delete both Content- headers from C# and the charset parameter from JavaScript

    var blobObject = new Blob([response.data], {type: 'application/zip'});
    

    If you really need to use Windows-1252, you can try to set it with the content type parameter.

     return File(zipStream.ToArray(), "application/octet-stream;charset=Windows-1252");
    

    Check this also: Charset Encoding in ASP.NET Response

    By the way, UTF-8 is the preferred charset encoding: W3 QA choosing encodings

    And, yes @nikneem, there is no need in the Content-Disposition and Content-Length headers. They will be generated automatically.