Search code examples
webpackjszip

Loading binary file with webpack and converting to Blob


I have a <input id=file-chooser" type="file"/> control that I allow a user to upload a .zip file with and I then hand that off to jszip for further processing.

I am trying to test this by loading a local .zip test file in webpack, converting to a Blob, and then manually firing the change event with the content of the file.

jszip is complaining that the zip file is not valid and I think I am messing something up on the conversion.

I've tried:

// Load file at webpack compilation time
const zipFileRaw = require("raw-loader!../test.zip");

// Convert to ArrayBuffer
const bytes = new Uint8Array(zipFileRaw.length);
for (var i = 0; i < zipFileRaw.length; ++i) {
  bytes[i] = zipFileRaw.charCodeAt(i);
}

// Construct a 'change' event with file Blob
const file = new Blob(bytes, { type: "application/zip" });
file.name = "test.zip";
const event = { type: "change", target: { files: [file] } };

// Fire the event
$("#file-chooser").trigger(event);

Firing the event works and my event handler is called. In the event handler for the change event I call jsZip.loadAsync(file) and I get:

Error: Can't find end of central directory : is this a zip file ?


Solution

  • I ended up getting this to work by using the url-loader along with this solution for converting base64 to a Blob.

    // Load file at webpack compilation time
    const zipFileRaw: string = require("url-loader!../test.zip");
    const [match, contentType, base64] = zipFileRaw.match(/^data:(.+);base64,(.*)$/);
    
    // Convert the base64 to a Blob
    // Souce: https://stackoverflow.com/a/20151856/626911
    const file = base64toBlob(base64, contentType);
    
    // Construct a 'change' event with file Blob
    const event: any = { type: "change", target: { files: [file] } };
    
    // Fire the event
    $("#file-chooser").trigger(event);