Attaching a file via RestAPI to a Confluence page draft

I upload a file via atlassian-connect-express to a confluence attachment, from a dynamic content macro.

this.httpClient(userAccountId).post('/rest/api/content/{id}/child/attachment', input);

input is

{
            pathParameters: {
                id: confluencePageId
            },
            formdata: {
                file: [
                    stream,
                    {
                        filename: `File-${processId}`
                    }
                ]
            },
            headers: {
                'X-Atlassian-Token': 'nocheck',
                'Content-Type': 'multipart/form-data'
            }
        }

That works fine. Unless I try this from a macro that has been created in a not yet published draft of a confluence page.

Two questions:

  1. Is it possible to use this endpoint with drafts
  2. If not, how can I determine from a dynamic content macro (custom editor) if the enclosing Confluence page is a draft and has never been published before?
1 Like

Hi @m.schmidt ,

I haven’t actually tested the following - it is based on my reading of the API.

POST /wiki/rest/api/content/{id}/child/attachment takes a query parameter status which defaults to current if not provided, but can be set to draft when the attachment should be added as part of the current draft. If your dynamic content macro is adding the attachment, then I suspect you always should set the status=draft query parameter so that the attachment occurs as part of the user’s drafting of the page.

By the way, to determine whether the page has not yet been published, you can call AP.context.getContext() and observe the property confluence.content.version. If the version is 1, then the page has not yet been published. Alternatively, there’s a content.version context parameter which you can use so long as the macro is not declare as cacheable: true.

Regards,
Dugald

I have also created [CONFCLOUD-71905] Guide required to explain Confluence content lifecycle concepts - Create and track feature requests for Atlassian products. since it seems like a gap in our documentation.

2 Likes

Your reply is very useful for me. Thank you.

As you mentioned, creating attachment to draft page can be done with POST /wiki/rest/api/content/{id}/child/attachment setting status=draft.

However, when I create a new page, the attached files to the draft page are lost.
Created page doesn’t have the attachments that the draft has.
I create pages via REST API POST /rest/api/content setting id=DraftPageId.

My steps are,

  1. create draft with POST /wiki/rest/api/content setting status=draft.
  2. attach file with POST /wiki/rest/api/content/{id}/child/attachment setting status=draft.
  3. create page with POST /wiki/rest/api/content setting id=DraftPageIdFromStep1.

Is there any way to attach files to drafts when creating pages?

1 Like

I really would like to do this. We didn’t solve it and ask the user to publish the page before.

1 Like

Hi @takafumiohtake and @m.schmidt ,

I’ve created a small demo app to show how to do this. Here’s how to use it:

  1. Install the app using the URL https://dx-page-attachment-adder.glitch.me/connect.json.
  2. Visit a page.
  3. Click the ... menu besides the Share button.
  4. Click the option Add attachment to a new page.
  5. Check a modal dialog appears.
  6. Click the Brows button to select an attachment.
  7. Click the Add attachment to a new page link.
  8. Observe that a few messages get added to the dialog. They should show the content ID of the published page.
  9. Visit the published page https://your-tenant.atlassian.net/wiki/spaces/{spaceKey}/pages/{contentId}
  10. Check the page is published and has the attachment.

Let me know if this helps.

Regards,
Dugald

2 Likes

Hi @dmorrow ,

Thank you very much for the demo and a quick reply.

I found out how to attach files to draft when creating a page.
It works for my app.

The correct steps are,

  1. create draft with POST /wiki/rest/api/content setting status=draft.
  2. attach file with POST /wiki/rest/api/content/{id}/child/attachment setting status=draft.
  3. update page with POST /wiki/rest/api/content/{id} setting status(in body)=current, status(in query)=draft, version.number=1, space.key=[SpaceKey]
3 Likes

Hi @takafumiohtake ,

Great to see you are unblocked. The steps you listed match what’s in my demo app and I suspect the trick is the different status in the query and body of the request at step 3.

Regards,
Dugald

1 Like

Yes. Exactly.
I couldn’t find it from the documentation.
I’m looking forward that it will improve via [CONFCLOUD-71905] Guide required to explain Confluence content lifecycle concepts - Create and track feature requests for Atlassian products..

1 Like

@dmorrow AP.context.getContext() in a custom macro ui returns an empty object for me in edit mode. Is there any other way of figuring out if a page has been published?

@PhilipFeldmann I do this. Not sure if there’s any better method…

const draftStatus= () =>
  new Promise((resolve) => {
    AP.navigator.getLocation((location) => {
      const contentId = location.context.contentId
      AP.request({
        url: `/rest/api/content/${contentId}`,
      })
        .then(() => resolve({ id: contentId, status: 'current' }))
        .catch(() => resolve({ id: contentId, status: 'draft' }))
    })
  })
2 Likes

Thank you! Yeah, that’s a reasonable workaround, even though the call to /content might fail for other reasons and this might occasionally result in a faulty “draft” status.

My current workaround is checking whether draftShareId is in the URL of the top window - but that also seems potentially flaky. Best thing would be if Atlassian fixes getContext :smiling_face_with_tear: