Pdfmake: Insert images by URL

Created on 16 Jan 2015  路  12Comments  路  Source: bpampuch/pdfmake

Hello, Is it possible to insert images by putting the url?
like this:
'If you specify width, image will scale proportionally',
{
image: 'http://www.mydomain.com/images/image1.jpg',
width: 150
},

Thanks!

Most helpful comment

canvas library https://github.com/Automattic/node-canvas is just great tool.

I solved it by using following function

const {createCanvas, loadImage} = require('canvas');
function getImage(url, size) {
    return loadImage(url).then(image => {
        const canvas = createCanvas(size, size);
        let ctx = canvas.getContext('2d');
        ctx.drawImage(image, 0, 0);
        return canvas.toDataURL();
    });
}

and then call the function as
const imageData = await getImage(imageUrl, size);

and finally used in pdfmake as

{
    image: 'data:image/jpeg,'+imageData,
    width: 100,
    height: 100,
}

I hope its helpful.

All 12 comments

Hi @onbermejo ,

that is unlikely, because it would make the whole library asynchronous. But you could create the data urls yourself before calling pdfmake. Look at this stack overflow: http://stackoverflow.com/questions/934012/get-image-data-in-javascript

Br, Johannes

Ok, thank you very much

I have the same problem, someone can help me?

My image URL is of AWS which throw CROS error on that

To avoid CORS:
@mustafajunwa

urlToBase64 = (url: string): Promise => new Promise((resolve, reject) => {
const img = new Image();
img.crossOrigin = 'Anonymous';
img.src = url;
img.onload = () => {
const canvas = document.createElement('canvas'),
ctx = canvas.getContext('2d');
canvas.height = img.height;
canvas.width = img.width;
ctx.drawImage(img, 0, 0);
resolve(canvas.toDataURL('image/jpeg'));
};
img.onerror = error => reject(error);
})

canvas library https://github.com/Automattic/node-canvas is just great tool.

I solved it by using following function

const {createCanvas, loadImage} = require('canvas');
function getImage(url, size) {
    return loadImage(url).then(image => {
        const canvas = createCanvas(size, size);
        let ctx = canvas.getContext('2d');
        ctx.drawImage(image, 0, 0);
        return canvas.toDataURL();
    });
}

and then call the function as
const imageData = await getImage(imageUrl, size);

and finally used in pdfmake as

{
    image: 'data:image/jpeg,'+imageData,
    width: 100,
    height: 100,
}

I hope its helpful.

Is it possible to add this an example to the official documentation? I spent hours looking for a solution till I came across this and it works perfectly!

@jthoenes @liborm85 @bpampuch

canvas library https://github.com/Automattic/node-canvas is just great tool.

I solved it by using following function

const {createCanvas, loadImage} = require('canvas');
function getImage(url, size) {
    return loadImage(url).then(image => {
        const canvas = createCanvas(size, size);
        let ctx = canvas.getContext('2d');
        ctx.drawImage(image, 0, 0);
        return canvas.toDataURL();
    });
}

and then call the function as
const imageData = await getImage(imageUrl, size);

and finally used in pdfmake as

{
    image: 'data:image/jpeg,'+imageData,
    width: 100,
    height: 100,
}

I hope its helpful.

Is it possible to add this an example to the official documentation? I spent hours looking for a solution till I came across this and it works perfectly!

@jthoenes @liborm85 @bpampuch

canvas library https://github.com/Automattic/node-canvas is just great tool.
I solved it by using following function

const {createCanvas, loadImage} = require('canvas');
function getImage(url, size) {
    return loadImage(url).then(image => {
        const canvas = createCanvas(size, size);
        let ctx = canvas.getContext('2d');
        ctx.drawImage(image, 0, 0);
        return canvas.toDataURL();
    });
}

and then call the function as
const imageData = await getImage(imageUrl, size);
and finally used in pdfmake as

{
    image: 'data:image/jpeg,'+imageData,
    width: 100,
    height: 100,
}

I hope its helpful.

this isn't working on client side apps like react right?

I use the following code to fetch images client-side, no dependencies. Main ideas:

  • Use image URL as key for image dictionary.
  • Fetch all images in a loop.
  • Load image with an img element
  • Draw image to canvas and get data URL from canvas.
function fetchImage (uri) {
  return new Promise(function (resolve, reject) {
    const image = new window.Image();
    image.onload = function () {
      var canvas = document.createElement('canvas');
      canvas.width = this.naturalWidth;
      canvas.height = this.naturalHeight;
      canvas.getContext('2d').drawImage(this, 0, 0);
      resolve(canvas.toDataURL('image/png'));
    };
    image.onerror = function (params) {
      reject(new Error('Cannot fetch image ' + uri + '.'));
    };
    image.src = uri;
  });
}

function createPDF() {
const doc = {
  content: [
    ...
    {
      image: 'https://xy.com/myimage.jpg'
    }
  ],
  images: {
    'https://xy.com/myimage.jpg': null
  }
};

const fetches = [];
doc.images.forEach(src => {
  fetches.push(fetchImage(src).then(data => { doc.images[src] = data; }));
});

Promise.all(fetches).then(() => {
  pdfMake.createPdf(doc).download('test.pdf');
});

I use the following code to fetch images client-side, no dependencies. Main ideas:

  • Use image URL as key for image dictionary.
  • Fetch all images in a loop.
  • Load image with an img element
  • Draw image to canvas and get data URL from canvas.
function fetchImage (uri) {
  return new Promise(function (resolve, reject) {
    const image = new window.Image();
    image.onload = function () {
      var canvas = document.createElement('canvas');
      canvas.width = this.naturalWidth;
      canvas.height = this.naturalHeight;
      canvas.getContext('2d').drawImage(this, 0, 0);
      resolve(canvas.toDataURL('image/png'));
    };
    image.onerror = function (params) {
      reject(new Error('Cannot fetch image ' + uri + '.'));
    };
    image.src = uri;
  });
}

function createPDF() {
const doc = {
  content: [
    ...
    {
      image: 'https://xy.com/myimage.jpg'
    }
  ],
  images: {
    'https://xy.com/myimage.jpg': null
  }
};

const fetches = [];
doc.images.forEach(src => {
  fetches.push(fetchImage(src).then(data => { doc.images[src] = data; }));
});

Promise.all(fetches).then(() => {
  pdfMake.createPdf(doc).download('test.pdf');
});
}

This really solved the problem for me on client side, i tried in vue and worked fine.

I was facing CORS issues with the Canvas method, even with node-canvas. This was the code that worked for me (client side):

fetchImage(url) {
  return fetch(url)
    .then((response) => response.blob())
    .then(
      (blob) =>
        new Promise((resolve, reject) => {
          const reader = new FileReader();
          reader.onloadend = () => resolve(reader.result);
          reader.onerror = reject;
          reader.readAsDataURL(blob);
        })
    );
}

@gruppler Thanks for your suggestion, the FileReader method is also more elegant. I created a gist:

https://gist.github.com/r0the/3fd5cbc15ab07940c59eb519fa5cbf3e

Was this page helpful?
0 / 5 - 0 ratings

Related issues

dgrice picture dgrice  路  3Comments

SummerSonnet picture SummerSonnet  路  3Comments

m-brudi picture m-brudi  路  3Comments

jokris1 picture jokris1  路  3Comments

michaelqiji picture michaelqiji  路  3Comments