Jszip: Running into problems upgrading to v3.0.0

Created on 15 May 2016  路  3Comments  路  Source: Stuk/jszip

It seems like some of the example code in the online documentation is not up to date for v3.0.0 yet. I believe that's what is confusing me as I can't seem to get my code to work with v3.0.0.
Please note: I'm not using node.js. I _am_ using JSZipUtils and FileSaver.

I'm getting a TypeError: zip.file(...) is null error on this line zip.file( tgmpaDir + '/example.php' ).async( 'string' ).then( function( content ). The file however does exist within the zip file.

Old code :

var tgmpaDir = 'TGM-Plugin-Activation-2.5.2';

JSZipUtils.getBinaryContent( '../releases/' + tgmpaDir + '.zip', function( err, data ) {
    if ( err ) {
        showMessage( 'Failed to retrieve TGMPA: ' + err, 'error' );
        return false;
    }

    try {

        zip = new JSZip( data );

        // Read a file from the zip
        exampleFileContent = zip.file( tgmpaDir + '/example.php' ).asText();
        // <snip> Adjusting exampleFileContent

        // Replace the original file with the new content.
        zip.file( tgmpaDir + '/example.php', exampleFileContent );

        if ( JSZip.support.blob ) {
            try {
                blob = zip.generate( { type:'blob' } );

                // Uses FileSaver.js.
                saveAs( blob, tgmpaDir + '-' + slug + '.zip' );

                showMessage( 'Custom TGMPA succesfully created!', 'success' );

            } catch ( e ) {
                showMessage( 'Failed to generate Custom TGMPA file: ' + e, 'error' );
            }
        } else {
            showMessage( 'This browser is not supported.', 'warning' );
        }

        return false;

    } catch ( e ) {
        showMessage( ' ' + e, 'error' );
    }
});

New code :

var tgmpaDir = 'TGM-Plugin-Activation-2.5.2';

JSZipUtils.getBinaryContent( '../releases/' + tgmpaDir + '.zip', function( err, data ) {
    if ( err ) {
        showMessage( 'Failed to retrieve TGMPA: ' + err, 'error' );
        return false;
    }

    try {
        zip = new JSZip();
        zip.loadAsync( data );


        zip.file( tgmpaDir + '/example.php' ).async( 'string' ).then( function( content ) {

            // <snip> Adjusting content

            // Replace the original file with the new content.
            zip.file( tgmpaDir + '/example.php', content );
        } );

        if ( JSZip.support.blob ) {
            try {
                zip.generateAsync( { type:'blob' } ).then( function( blob ) {

                    // Uses FileSaver.js.
                    saveAs( blob, tgmpaDir + '-' + slug + '.zip' );

                    showMessage( 'Custom TGMPA succesfully created!', 'success' );
                } );

            } catch ( e ) {
                showMessage( 'Failed to generate Custom TGMPA file: ' + e, 'error' );
            }
        } else {
            showMessage( 'This browser is not supported.', 'warning' );
        }

        return false;

    } catch ( e ) {
        showMessage( ' ' + e, 'error' );
    }
});
questiosupport

Most helpful comment

Do I understand correctly that there is no way anymore to run jsZip without using async and promises ?

That's correct.

I also missed a removed constructor in documentation/api_jszip/file_name.md. Thanks for the hint !

All 3 comments

The issue comes from

zip = new JSZip();
zip.loadAsync( data );
zip.file( tgmpaDir + '/example.php' )....

loadAsync is asynchronous: when you try to read example.php, zip is still empty. loadAsync returns a Promise, you need to wait for the result:

JSZip.loadAsync(data).then(function(zip){
  // ...
});

The upgrade guide is indeed confusing as it doesn't hint this change (I'll fix that).

You could write the new code like this:

var tgmpaDir = 'TGM-Plugin-Activation-2.5.2';

if ( !JSZip.support.blob ) {
    showMessage( 'This browser is not supported.', 'warning' );
    return;
}
JSZipUtils.getBinaryContent( '../releases/' + tgmpaDir + '.zip', function( err, data ) {
    if ( err ) {
        showMessage( 'Failed to retrieve TGMPA: ' + err, 'error' );
        return false;
    }

    JSZip.loadAsync(data).then(function updateContent(zip) {
        // replace the original file with a promise of the new content
        var updatedContent = zip.file( tgmpaDir + '/example.php' ).async( 'string' ).then( function( content ) {
            // <snip> Adjusting content
            return newContent;
        });
        // updatedContent is a promise of string, resolved by JSZip
        zip.file( tgmpaDir + '/example.php', updatedContent );

        return zip;
    }).then(function generateZip(zip) {
        return zip.generateAsync( { type:'blob' } );
    }).then(function success(blob) {
        // Uses FileSaver.js.
        saveAs( blob, tgmpaDir + '-' + slug + '.zip' );

        showMessage( 'Custom TGMPA succesfully created!', 'success' );
    }, function failure(e){
        showMessage( 'Failed to generate Custom TGMPA file: ' + e, 'error' );
    });
    return false;
});

@dduponchel Thank you very much for your response. That's very helpful.
I'll go and run some tests with that.

Do I understand correctly that there is no way anymore to run jsZip without using async and promises ?

In that case you may want to adjust/update the documentation on the following page for the new code structure (still shows three old examples):
https://github.com/Stuk/jszip/blob/gh-pages/documentation/howto/read_zip.md

Do I understand correctly that there is no way anymore to run jsZip without using async and promises ?

That's correct.

I also missed a removed constructor in documentation/api_jszip/file_name.md. Thanks for the hint !

Was this page helpful?
0 / 5 - 0 ratings

Related issues

sethdorris picture sethdorris  路  4Comments

ghigt picture ghigt  路  4Comments

jimmywarting picture jimmywarting  路  4Comments

zizizi17 picture zizizi17  路  6Comments

sriramkp picture sriramkp  路  6Comments