How to recieve a pdf file with forge-api?

Hi guys,

I’m creating a forge app, which collects some data and sends it to an external Node.js/express server, where it generates a pdf file out of that data. This pdf file is sent back to my forge app, but I’m not able to recieve it as a file. Instead I get my typical APIResponse object, which wouldn’t be a problem, if I could puzzle my pdf together out of the arrayBuffer. But if I try to send the buffer to my frontend to build the file, only an empty json object comes in. I don’t know why, maybe to buffer is too big? Then I tried a little workaround to write the buffer into a String, but this takes longer than 10 seconds and the request stops with a timeout. Could anyone please tell me what I’m doing wrong, or better how to send pdf files right?

Here are some code snippets.

The Node.js/express server

app.post('/createOffer', async (req, res)=>{
  const sampleArg = req.body;
  const filepath = pdf.createPdf(sampleArg);
  const file = fs.readFileSync(filepath);
  res.contentType("application/pdf");
  return res.send(file)
});

backend in my forge app

resolver.define('exportPdf', async (req) => {
  const data = req.payload;
  const result = await api.fetch("https://url.net:PORT/createPdf", {
    method: "POST",
    headers: {
      'Content-Type': 'application/pdf',
      Accept: 'application/pdf'
    }, 
    body: JSON.stringify(data)
  })

  const ab = await result.arrayBuffer();
  const uint = new Uint8Array(ab);

  //this takes all the time, its 1.6million bytes to write into that String
  let string = "";
  uint.forEach(byte => string += byte.toString(16).padStart(2, "0") + " ")

  return string;
});

Cheers and thank you a lot!

2 Likes

Hey @PeterOrbok,

This is a great use case. I’ll ask my team about the array buffers and just generally about recommended approaches here.

Large files are a use case that the Forge lambda hasn’t currently been built very well to achieve yet. Are you able to bypass the Forge lambda for the part of the request that gets the file, and instead make the request from the frontend? If you need authentication or authorize, I’m not a security expert, but I’m aware of methods such as using the lambda to auth and get a randomised, unguessable URL on your external server, and then pass that to the frontend to get the PDF?

2 Likes

Hey @kchan,

I solved the problem using 2 requests.
First a POST request to send the data to the backend and create the file on the server. The response is the filepath on the server.
Then I send GET request which sends me the pdf file back. (Actually I still wonder why I could send files via GET but not via POST) …but it works like a charm :smiley:

3 Likes

That’s great to hear @PeterOrbok! Thanks for sharing that with us.

I’m really intrigued as to why sending the file via GET works! Do you know what type the result you return from the resolver ends up being? And what type is it when you access it in the front-end?

Hey @kchan,

I should have specified it better. It made the GET request directly out of the frontend.
Here is the code for that:

const downloadFile = response => {
    const query = `?filepath=${response.filepath}`

    let link = document.createElement('a');
    link.href = `https://url.com/getPdf${query}`; 
    link.download = "file.pdf";
    link.click();
    link.remove();
}
3 Likes