JSZip Creating Corrupt JPG Image
Asked Answered
I

2

5

I'm tring to add a JPG image I created with html2canvas to a Zip file using JSZip. When I save the raw JPG file, it comes out fine. But when I zip it, the image comes out corrupt (when I open the image file, no data appears). Here is my script:

<!DOCTYPE html>
<html>
    <head>
        <script src="https://stuk.github.io/jszip/dist/jszip.js"></script>
        <script src="http://html2canvas.hertzen.com/dist/html2canvas.min.js"></script>
        <script type="text/javascript" src="FileSaver.min.js"></script>
    </head>
    <body>
        <div id="capture" style="padding: 0; background: #f5da55; width: 400px; height: 200px;">
            <h4 style="color: #000; ">Hello, world!</h4>
        </div>

        <script type="text/javascript">
            html2canvas( document.querySelector("#capture") ).then(canvas => {
                var img = new Image(); img.src = canvas.toDataURL( 'image/jpeg' );

                // * * * This JPG is good:    
                saveAs( img.src, 'file1.jpg');

                var zip = new JSZip();

                // Add a file to the zip file, in this case an image with data URI as contents
                // * * * This JPG comes out corrupted:    
                zip.file( 'file2.jpg', img.src, {binary: true} );

                // Generate the zip file asynchronously
                zip.generateAsync({type:"blob"}).then(function(content) {
                    saveAs( content, 'archive.zip' );
                });
            });
        </script>
    </body>
</html>

Please help me add the data URI image to the zip file. Many thanks!

Inexpensive answered 27/3, 2019 at 19:47 Comment(2)
Is the image file in the zip 0 bytes or..?Ehlers
It does have a size, 5 kb. Which tells me it is writing data, but maybe not in the correct format? Because when I open the image in Photoshop, the browser or any image viewer, I get a message saying the file is corrupt and nothing shows.Inexpensive
I
5

I ended up answering my own question. The solution was to first convert the Base64 data URI image to BLOB. To do that, I used the following custom function:

function dataURItoBlob( dataURI ) {
    // Convert Base64 to raw binary data held in a string.

    var byteString = atob(dataURI.split(',')[1]);

    // Separate the MIME component.
    var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0]

    // Write the bytes of the string to an ArrayBuffer.
    var ab = new ArrayBuffer(byteString.length);
    var ia = new Uint8Array(ab);
    for (var i = 0; i < byteString.length; i++) {
        ia[i] = byteString.charCodeAt(i);
    }

    // Write the ArrayBuffer to a BLOB and you're done.
    var bb = new Blob([ab]);

    return bb;
}

var image = dataURItoBlob( img.src );

Drewness's suggestion works, too, but I prefer my method since canvas.toBlob() doesn't return a value.

Inexpensive answered 28/3, 2019 at 19:45 Comment(0)
E
1

You can convert it to a blob using canvas.toBlob. This is what the FileSaver .saveAs does.

var canvas = document.querySelector("#capture");

canvas.toBlob(function (blob) {
  zip.file('file2.jpg', blob);
});

Fun fact, the HTML5 canvas.toBlob is not supported in all browsers. The canvas-toBlob.js is a cross-browser polyfill for this.

Ehlers answered 28/3, 2019 at 14:25 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.