0

I am building a function that creates a canvas from a container div on a webpage. I ran into an issue with the site images not being allowed on the canvas due to CORs because they're "external images".

They're "external images" because we're working with a site-builder/host(https://www.knack.com/) that puts all uploaded images into their AWS bucket. If I upload an image to "mysite.com" they will save them into the database as aws hosted images. That makes the image src = "https://s3.amazonaws.com/assets.knackhq.com/assets/numbers/numbers/original/filename.jpg".

The images all display fine in browser, but in trying to create a canvas the CORs errors come out.

Now, I found a "workaround". If I convert the image url to a Data URI the image is added to the canvas without problem.

There's an issue with the workaround though. Manually sending the urls through an online converter site works, but is unfeasible for the amount of images we have and since we will be adding more constantly. I've tried many methods of using JS to convert the images to data URI but so far, those methods keep failing due to CORs errors as well.

In short:

  • I want to convert images to a clean canvas but I can't because they're external images
  • I'm stuck dealing with the images as external images due to the constraints and processes of the site I'm working with
  • I do not have access to the server to change settings regarding CORs or setting up any sort of converter on the server
  • If I convert the external images to a data URI they work great
  • I need to convert the images dynamically as it is unfeasible to manually convert every image and then code it in
  • I don't have a way of dynamically converting external images to data URIs

Does anyone know of a working method to do this in JS or a converter API I can call in my code to perform the conversion? Or any other solution at all? I'm pretty much open to anything that can work with the constraints I've listed up here.

sideshowbarker
  • 81,827
  • 26
  • 193
  • 197
  • See https://stackoverflow.com/a/43881141/441757 for one option you could consider, which is to set up a CORS proxy and make the requests through that proxy rather than directly to the `https://s3.amazonaws.com/assets.knackhq.com/assets` URLs. – sideshowbarker Jun 10 '21 at 19:05
  • This was it! I knew about CORs proxies, but this guide you posted told me how to properly use them and that was the solution! I used a CORs Proxy (https://api.codetabs.com/v1/proxy?quest=) in front of the image urls and then ran them through the canvas to dataURL function like this one: https://www.tutorialspoint.com/convert-image-to-data-uri-with-javascript. Part of that dataURI function was to replace the img src in the DOM with the dataURI. This avoided the CORs errors and delivered me data URI images that I could retain when I converted the canvas to PDF. – t73designs Jun 11 '21 at 15:15

1 Answers1

0

Sideshowbarker delivered me a guide on CORs proxies that solved this issue!

I used a CORs Proxy (https://api.codetabs.com/v1/proxy?quest=) in front of the image urls and then ran them through a canvas to dataURL function:

function replace_img(url, img_2_replace) {
    // To bypass errors (“Tainted canvases may not be exported” or “SecurityError: The operation is insecure”)
    // The browser must load the image via non-authenticated request and following CORS headers
    var img = new Image();
    img.crossOrigin = 'Anonymous';
    img.src = url;
    // The magic begins after the image is successfully loaded
    img.onload = function () {
    var canvas = document.createElement('canvas'),
        ctx = canvas.getContext('2d');

    canvas.height = img.naturalHeight;
    canvas.width = img.naturalWidth;
    ctx.drawImage(img, 0, 0);

    // Unfortunately, we cannot keep the original image type, so all images will be converted to PNG
    // For this reason, we cannot get the original Base64 string
    var uri = canvas.toDataURL('image/jpg'),
        b64 = uri.replace(/^data:image\/jpg;base64,/, "");

    //console.log(b64); //-> "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQImWP4z8DwHwAFAAH/q842iQAAAABJRU5ErkJggg=="
    var replace = document.getElementById(img_2_replace);
    replace.src= b64;  
    };
    

    }

Part of that dataURI function was to replace the img src in the DOM with the dataURI. This avoided the CORs errors and delivered me data URI images that I could retain when I converted the canvas to PDF.