docxImage not rendering base64 image sent over API (instead outputs base64 json)
-
Hey JSReprot Forum!
I build a system around jsreport, or better to say its API, and everything is working so far except the {{docxImage}} tag.
The goal is to use a docx document as a template and also get a docx document back, filled with data.
This is how the docx document looks like used as a template:
I am sending the following API call (I shortened the base64 image code)
{ "template": { "name": "testtemplateid-main", "recipe": "docx", "engine": "handlebars", "docx": { "templateAssetShortid": "testtemplateid-docx" } }, "data": { "testvalue":"this is the test value", "blop": { "name":"name of the blop", "value":"value of the blop" }, "entries": [ { "name":"first entry name", "id":"first entry ID", "images": [ "data:image\/jpeg;base64,\/9j\/4AAQS .... WzZUf\/\/Z", "data:image\/jpeg;base64,\/9j\/4AAQS .... gTNKqzwiiiiJI\/BfOn\/2Q==" ] }], "entries_not_empty":true } }
And this here is the docx after rendering:
That strange output instead of the image is another base64 json.
This is the marked string from the image above, base64 decoded:{"src":"data:image/jpeg;base64,/9j/4AAQS .... WzZUf//Z","usePlaceholderSize":false}
So why is JSReport putting two $ signs around that {{docxImage ...}} tag. And then this base64 encoded json?
I could not find any information on the official sites about that behaviour. The only source so far is this: https://jsreport.net/learn/docx but the topic about docximage is very short and not detailed.
The attempt I used here is from this post: https://forum.jsreport.net/topic/1454/array-in-array
I also tried:
- Without a loop, just putting the base64 code inside like this:
"entries": [ { ... "image01": "data:image\/jpeg;base64,\/9j\/4AAQS .... WzZUf\/\/Z" ... }],
But I get the same result, a base64 encoded json with this "src":"..." in it.
-
I also tried "src" instead of "image01", same result.
-
Also tried to put the rendered decoded output into "image01" like this:
"entries": [ { ... "image01": { "src": "data:image\/jpeg;base64,\/9j\/4AAQS .... WzZUf\/\/Z" } ... }],
Results in an error:
{ "message": "Error while executing docx recipe. Error while executing templating engine. options.hash.src.startsWith is not a function. Error on line 144:25.\n\n 142 | \n 143 | if (\n> 144 | !options.hash.src.startsWith('data:image/png;base64,') &&\n | ^\n 145 | !options.hash.src.startsWith('data:image/jpeg;base64,') &&\n 146 | !options.hash.src.startsWith('http://') &&\n 147 | !options.hash.src.startsWith('https://')\n\n",
- also leaving it encoded, like this:
"entries": [ { ... "image01": "eyJzcmMiOiJ...WxzZX0=" ... }],
This gives an error from jsreport:
{ "message": "Error while executing docx recipe. Error while executing templating engine. docxImage helper requires src parameter to be valid data uri for png or jpeg image or a valid url. Got eyJzcmMiOiJkYbhdRjPSlXptGC5yc+opUdC2YSfh91FuB3kI6oNx9KhezvB.....zZX0=. Error on line 149:13.\n\n 147 | !options.hash.src.startsWith('https://')\n 148 | ) {\n> 149 | throw new Error(\n | ^\n 150 | 'docxImage helper requires src parameter to be valid data uri for png or jpeg image or a valid url. Got ' +\n 151 | options.hash.src\n 152 | )\n\n",
- And also everything within the $ signs:
"entries": [ { ... "image01": "$docxImageeyJzcmMiOiJkYXRhOmlt....aegv=$" ... }],
What results in the same error as above.
I would really appreciate if anyone knows what I am mistaken here, or can provide some more detailed explanation / manual / resource to understand how this mechanism works.
Thanks and stay healthy!
-
I don't know which format you should supply, but if it should only be the actual base64 data you need to remove the initial properties.
Try this:
yourString.replace(/^data:image\/\w+;base64,/, '');
-
Here is a playground example I made with this docx file and similair data:
https://playground.jsreport.net/w/anon/Q8hXVLX0
I tried that and all kind of stuff but it does not work. Here are some examples again and new ones
- Using typical base64 header + encoded image:
- Just the part with the encoded image without header
- Using the complete output after render
- Using just the encoded part from the output after render
- Using src nested inside image01
- Adding the parameter usePlaceHolderSize=false, as in the encoded output after render
not working
- using src instdead of image01 in case the variable name is important
- Using an URI to an image
- And I tried much more
...
The Base64 code works, as seen here:
Maybe I missread or just oversaw something, in that case please tell me, but I am currently in the situation to say, that this statement
from the manual (https://jsreport.net/learn/docx) should be reworked.
Are there any other possibilities, to get an image into a docx through an API request / sending data in json format over the API?
-
@itdl1 as per the docxImage instructions the docx template needs to have a real word image defined, then the docxImage helper call needs to go in a bookmark. we don't support generating an image from scratch using just the helper alone.
here is your update example working: https://playground.jsreport.net/w/bjrmatos/4EZexY23
the shape of what you need to pass in the API is the same content data "testdata01" in the playground, so the image should be in data base64 uri
again, to set up the image correctly read the docxImage instructions and you should be good.
-
FYI, i noticed in the picture I have sent that your #if condiction was having some spaces so it was not working as expected before, the spaces were removed in the playground link and now it works normally (the #if call does not end in the final document)
-
Oh ok, thank you a lot! I was interpreting the two "bookmark-like image" and "base64 code" facts as independent properties, not correlated to each other necessarily, I tought to create an image in word first and fill it is best practice, but the statement I mentioned was also telling that pure base64 is also working.
Thanks for clarifying that!
Do you know if there are any other possibilities or workarounds to achieve the goal I am aiming for (inserting images without the need to "position" them in the template before) through jsreport? Maybe through helper scripts or something? I don't need a full solution, some buzzwords to google for would be fine.
Currently I am thinking about doing some PHP-Work, inserting "word-code for images" into a template-copy before sending it to jsreport, but a "purer" solution would be nice of course.
Thanks again, have a nice day and stay healthy!
-
Do you know if there are any other possibilities or workarounds to achieve the goal I am aiming for (inserting images without the need to "position" them in the template before) through jsreport?
for now, this is the only way to do it, basically, all our approaches require the docx element to exists (image, table, list, etc) in order to modify it or create more items based on the template element and data
-
Hi - I've tried passing the URL in, but the image in the document gets changed to...
$docxImageeyJzcmMiOiJodHRwczovL3Nhb25lZ292czEwcHJvZHVrc291dGgwMS5ibG9iLmNvcmUud2luZG93cy5uZXQvb25lZ292czEwL0JyYW5kaW5nL2VkdWNhdGlvbkdhdGVzaGVhZC9HYXRlaGVhZExvZ28uanBnIiwidXNlUGxhY2Vob2xkZXJTaXplIjpmYWxzZX0=$
-
Your example looks like you're passing the base64 image data in - is that right?
-
@Paul-Hepple yes, the example above uses the base64 data URI in the data as the input, the same example also works if you give it an URL to an image, if you don't get it to work with the URL maybe is because the server which is hosting the image is not correctly serving it