Forge app custom UI, in backend code how to get file in frontend?

I build a forge app with custom UI which get a file from user then upload to a confluence page.
I cannot achieve this because

  1. In frontend cannot make a request to post the file to confluence page (because it violates the following Content Security Policy directive: "connect-src ‘self’)
  2. In backend it can post a file to confluence page but in backend cannot get the file from frontend via payload, it is empty object

App.tsx

function App() {
  const onAdd = async (event: ChangeEvent<HTMLInputElement>) => {
    try {
      const file = event.target.files?.[0] as File;
      const fileName = file.name;
      console.log(file);
      console.log(fileName);

      const response = await uploadFileToConfluencePage(file, fileName);
      console.log(response);
    } catch (error) {
      console.log('Failed to upload files');
      console.error(error);
    }
  };

  return (
    <div>
      <input type="file" onChange={onAdd} />
    </div>
  );
}

export default App;

index.js

resolver.define('uploadFileToConfluencePage', async (req) => {
  const { file, fileName } = req.payload;
  console.log(req.payload);
});


Hi all,

Is there anyone facing same issue? or in such a use case that in the Jira forge app, upload file to Confluence page. Is there any achievable approach?

I’m not that familiar with using Forge yet, but this resembles message passing to me, like you would with a browser add-on using a worker thread and a userscript in the browser (such as with manifest V3 browser extensions).

There, typed objects cannot be passed in the messaging because most objects are passed by reference and not by value.
so something like

a = {"foo": "bar"}
b = a

a.foo = "baz"
console.log(`result: ${b.foo}`)
// result: baz

Since the line b = a copies the reference to the object a into b instead of making a deep-copy of a.

The same thing is probably happening here where you are trying to pass your file object by reference which will never make it through the message system.
To get around this, you will need to break down the important parts of your object that you want to send into primitive values and send those.

You should be able to create a plain object and just set the properties to actual copies of the data as primitives, so you may need to Base64 encode your file data as a string before passing that back, along with any file metadata that you want and pack all that up into a new object literal and send that through the messaging system.

Worst case scenario, you should be able to JSON.stringify() your object with all the needed properties broken down to primitives and send it all over as a JSON string to decode on the front-end if I am not mistaken.
It won’t be as clean looking, but I feel like that should get you where you are going if I am not mistaken.

NOTE:
Although I am Atlassian staff, I am but a humble support engineer and not a dedicated developer, so please take my response with a grain of salt. I in no way wish to imply that this is the “correct” or even a “good” solution for this issue. Furthermore, I have not tested this myself. This is just a musing that I had while looking for a way to do something like this myself.