1

I am making a "simple" bookmarklet for 4chan (potentially extensible to other sites) that will download all images in the current thread as a zip archive. The images displayed in a 4chan thread are just thumbnails. The images themselves are provided as links that can be accessed by clicking the thumbnails.

My code should work almost perfectly. I found the class that contains the links to the full-sized images. I select all of these 's with jquery. I am using JSZip to compile the images. But JSZip requires the image data encoded in base64. After scourging SO for methods to do this, it seems almost unanimous that drawing an image onto a canvas and converting the image to base64 that way is the best way to do it. However, since 4chan provides links to its images instead of them being right there in the site, the canvas becomes "tainted" when I draw a linked image onto it, and I cannot get the base64 encoding from it.

How can I do this differently so that it works? Is there a way around the cross origin thing? I tried adding crossorigin="anonymous" to the images I'm creating, but it doesn't work.

jchitel
  • 2,999
  • 4
  • 36
  • 49
  • 1
    If the images you want to deliver are not hosted on the same server as your webpages, you will always get a CORS tainted canvas. A common workaround is to wrap the imagedata in JSONP which delivers the imagedata as a "script". Scripts are not subject to CORS and therefore won't taint your canvas. – markE Jan 04 '14 at 17:46

2 Answers2

2
var getDataUri = function (targetUrl, callback) {
    var xhr = new XMLHttpRequest();
    xhr.onload = function () {
        var reader = new FileReader();
        reader.onloadend = function () {
            callback(reader.result);
        };
        reader.readAsDataURL(xhr.response);
    };
    var proxyUrl = 'https://cors-anywhere.herokuapp.com/';
    xhr.open('GET', proxyUrl + targetUrl);
    xhr.responseType = 'blob';
    xhr.send();
};
getDataUri(path, function (base64) {
    // base64 availlable here
})

While converting into base64 you can use a proxy URL (https://cors-anywhere.herokuapp.com/) before your image path to avoid cross-origin issue

Manish Mittal
  • 207
  • 2
  • 10
0

Check the window.btoa() (doc) which you can use to base-64 encode binary data.

There shouldn't be need for canvas in this case, just download the data with "ajax" (SO) instead.

If you use canvas and the image is for example JPEG you will get a re-compressed image as well (reduced quality) and it will be slower so I wouldn't recommend canvas in this case.

Here is a solution as well (SO).

Community
  • 1
  • 1
  • btoa() definitely looks like it can work for me, but it only converts a string to base64. How do I get an image in the form of a string? – jchitel Jan 04 '14 at 18:51
  • @jchitel ay, yeah, you're right. I forgot it took only a string (and the very foundation of the answer.. 8-|). Sorry about that. Check out the solution in the last link instead - it will encode binary data to base64. –  Jan 04 '14 at 19:17