Jebathon
Jebathon

Reputation: 4561

SuiteScript 2.0 xmlToPdf - add image to PDF

I have an image in File Cabinet that I want to add to my PDF. I have a script that creates a PDF and adds that image to it.

I tested the link https://system.na2.netsuite.com${imgURL} on my browser and the image loads. However I get a strange error when I try to add it to my PDF below:

var myImageFromFileCabinet = file.load({id:10202});
imgURL = myImageFromFileCabinet.url;

xmlStr = `<body><img src="https://system.na2.netsuite.com${imgURL}"></body>`;

let pdfFile = render.xmlToPdf({ xmlString: xmlStr });
context.response.writeFile({
    file: pdfFile,
    isInline: true
});

"type":"error.SuiteScriptError","name":"USER_ERROR","message":"Error Parsing XML: The reference to entity "c" must end with the ';' delimiter.

How can I add an image to a PDF?

Upvotes: 0

Views: 1084

Answers (1)

erictgrubaugh
erictgrubaugh

Reputation: 8847

TLDR: Escape the URL string for use in XML

The root cause of your error is that you are not escaping the URL for use in XML. The & characters in the URL must be escaped as XML/HTML entities. You can do this with the N/xml.escape() function:

const imgURL = xml.escape({xmlText: myImageFromFileCabinet.url});

That said, there were several other issues I had to resolve with this code along the way:

Outer tag must be pdf

The initial error I got when running this code was:

Error Parsing XML: Outer tag is body, should be pdf or pdfset

I fixed this by wrapping the <body> in a <pdf>.

img tag must be closed

Next I needed to close the <img> with </img> (or /> whichever you prefer).

Summary

My full working onRequest looks like:

  const onRequest = (context) => {
    const myImageFromFileCabinet = file.load({id:1820});
    const imgURL = xml.escape({xmlText: myImageFromFileCabinet.url});

    const xmlString = `<pdf><body><img src="https://system.na2.netsuite.com${imgURL}"/></body></pdf>`;

    const pdfFile = render.xmlToPdf({ xmlString });
    context.response.writeFile({
      file: pdfFile,
      isInline: true
    });
  };

Note that I've also made some minor changes like renaming variables and adding some const keywords, as well as of course changing the image's internal ID for my own account.

Upvotes: 2

Related Questions