1

I'm using html2pdf.js to be able generate PDF documents of WEB pages.

The function is looking like:

html2pdf(someNode, {
  margin: 3,
  filename: 'name.pdf,
  image: { type: 'jpeg', quality: 0.98 },
  html2canvas: {
    scale: 2,
    useCORS: true,
    width: 1300,
    allowTaint: false,
    logging: false,
    proxy: 'https://bucket-name.s3.ap-northeast-1.amazonaws.com' 
  },
  jsPDF: {
    format: 'A4',
    orientation: 'landscape',
    unit: 'mm'
  },
  enableLinks: false
}).then(() => {...})

When I run html2pdf I'm getting error:

Access to image at 'https://bucket-name.s3.ap-northeast-1.amazonaws.com/image.jpg' from origin 'https://client.exampledomain.com' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

My development S3-like server is always returning access-control-allow-origin: * header and I able generate PDF without problem.

However S3 is responding access-control-allow-origin: https://client.exampledomain.com only if I set origin: https://client.exampledomain.com request header. But in some reason html2pdf doesn't add Origin header. I tried to change useCORS, allowTaint, proxy parameters without luck.

Looks like chrome is caching requests and if first request was sent without crossorigin headers, then other requests will be send with same headers as first request. And it is possible to set crossorigin="anonymous" for target image. However my image is a CSS image:

<div
  style="background-image:https://bucket-name.s3.ap-northeast-1.amazonaws.com/image.jpg"
></div>

And I couldn't find how to set crossorigin="anonymous" for background images.

Is it possible to set origin header for exact request manually or clear cache using javascript or maybe here is any other workaround how to load cross-origin image using html2canvas?

PS yes I know here is many questions about html2canvas and CORS errors but I already check most of it and did all recommendations mentioned there without any luck

rzlvmp
  • 7,512
  • 5
  • 16
  • 45
  • If you are using an API, you need to allow cors on the API side. For example, if you are booting the ten hundred with localhost:3000, you must allow 3000 ports on the api side. Also, if you are using google chrome as a browser, there is a plugin called "Cors", you can activate it and try your web page. – alierguc May 15 '23 at 10:27
  • 1. I'm not using API, I'm using direct Amazon S3 URLs to download images. 2. That is not a solution to ask our every customer to install plugin called `Cors`. The problem appear at the production environment – rzlvmp May 15 '23 at 10:32

1 Answers1

0

Finally, I gave up and added hidden extra image to be able add crossorigin="anonymous" parameter:

<div class="image-to-download"
  style="background-image:https://blahblah.amazonaws.com/image.jpg?placeholder="
><img alt="" style="display:none;" src="https://blahblah.amazonaws.com/image.jpg?withheaders=yes" crossorigin="anonymous">
</div>

And replacing placeholder= query parameter with withheaders=yes to be able use cached resource with CORS headers instead of CORSless one:

html2pdf(someNode, {
  ...
  html2canvas: {
    ...
    proxy: 'https://blahblah.amazonaws.com',
    onclone: (doc) => {
      let img;
      // update URLs to load cached cross-originated images
      for (img of doc.getElementsByClassName('image-to-download')) {
        img.style.backgroundImage = img.style.backgroundImage.replace('?placeholder=', '?withheaders=yes');
      }
    }
  },
  jsPDF: {
    ...
  },
  enableLinks: false
}).then(() => {...})
rzlvmp
  • 7,512
  • 5
  • 16
  • 45