Search code examples
javascriptbrowserifyzlib

How to download gzip compressed file generated from string with client-sided javascript


I basically have a site that I want to work fully client sided and it needs to be able to receive gziped xml file, decompress it, modify some stuff and then compress it and prompt user to download it.

I have the receiving/decompressing part working using zlib and drag-and-drop-files with browserify, but when I compress file and download it, it can't be decompressed because it apparently has an "invalid header".

Working receiving/decompressing part:

const zlib = require('zlib')
const drop = require('drag-and-drop-files')
const fileReaderStream = require('filereader-stream')
const concat = require('concat-stream')
const $ = require('jquery')

drop(document.getElementById('drop'), function (files) {
    var file = files[0]


    fileReaderStream(file).pipe(
        concat(function (contents) {
            var output = zlib.gunzipSync(contents).toString('utf-8')
            console.log('File loaded successfully')
            var xmlData = $.parseXML(output)
            doSomething(xmlData)
        })
    )
})

And not working compressing/downloading part:

var string = $(this).prop('outerHTML')

var output = zlib.gzipSync(string).toString('utf-8')

var a = document.createElement('a')
a.href = 'data:text/plain;charset=utf-8,' + encodeURIComponent(output)
a.download = `${name}.gz`
a.click()

File gets downloaded correctly but it appears to be corrupted. When I skip the compression and just prompt user to download raw xml as text file everything works fine.

I would really appreciate if anyone could tell me how this could be fixed.


Edit 1 - tried using blobs:
var output = zlib.gzipSync(string).toString('utf-8')

var blob = new Blob([output], { type: 'application/gzip' })
var blobUrl = URL.createObjectURL(blob)

var a = document.createElement('a')
a.href = blobUrl
a.download = `${name}.gz`
a.click()

The result is unfortunately the same.


Solution

  • I managed to make the blob version work, it appears that converting to string before creating blob was causing issues.

    var output = zlib.gzipSync(string)
    var blob = new Blob([output.buffer], { type: 'application/gzip' })
    

    Thanks everyone who suggested to use blob.