Sometimes Confluence users will report that their attachments have disappeared, with an 'Unknown Attachment' placeholder image showing:
The weird thing is that the attachment(s) do actually exist, attached to the page. It's just the image reference in the page that's broken.
If you view the Confluence page source through the Source Editor plugin, you'll see something weird: the 'Unknown Attachment' isn't Confluence saying "hey, there's no attachment by this name any more". It is in fact an embedded image of the 'unknown-attachment' image:
I've seen this on a few Confluence instances, and I have no idea how pages get to be like this. I suspect there is copy and pasting going on. Another weird thing: the URL is 'http://', not 'https://'.
If you have any ideas, please leave a comment!
To see if any of your Confluence's pages are affected by this, run this SQL on the database (Postgres-flavoured):
select 'https://confluence.mycompany.com/pages/viewpage.action?pageId=' || contentid AS url, title, lastmoddate from content JOIN bodycontent USING (contentid) WHERE content_status='current' and prevver is null and body like '%/plugins/servlet/confluence/placeholder/unknown-attachment%'; |
Since the image attachments are actually there, it's just a matter of editing the page and replacing the 'Unknown Attachment' images with the correct images.
Easier said than done sometimes, especially if the page has been edited many times after the images were corrupted. You'll need to loop tediously through the page history, finding the point at which the image(s) were deleted, then fix the current page's images.
This is exceptionally tedious, but some SQL can help ease the pain:
contentid
IDs of affected pages, using the SQL above. Store the contentid
list in a text file.Now, for each contentid
(for example, 22432553) run this SQL:
select baseurl || current AS current , baseurl || bad AS bad , baseurl || good AS good from ( select baseurl , current , contentid AS bad , lastmoddate , lag(contentid, 1) over (order by lastmoddate) AS good , (body ~ 'unknown-attachment') missingattach from (VALUES (22432553)) AS t (current) CROSS JOIN (VALUES ('https://confluence.example.com/pages/viewpage.action?pageId=')) AS b(baseurl) CROSS JOIN content JOIN bodycontent USING (contentid) WHERE content_status='current' and (contentid= current or prevver = current) ORDER BY lastmoddate ) x where missingattach=true limit 1; |
This will give you three URLs: the current page, the first 'gone bad' revision, and the 'just before we went bad' revision:
confluence=> select baseurl || current AS current , baseurl || bad AS bad , baseurl || good AS good from ( select baseurl , current , contentid AS bad , lastmoddate , lag(contentid, 1) over (order by lastmoddate) AS good , (body ~ 'unknown-attachment') missingattach from (VALUES (22432553)) AS t (current) CROSS JOIN (VALUES ('https://confluence.example.com/pages/viewpage.action?pageId=')) AS b(baseurl) CROSS JOIN content JOIN bodycontent USING (contentid) WHERE content_status='current' and (contentid= current or prevver = current) ORDER BY lastmoddate ) x where missingattach=true limit 1; ┌─[ RECORD 1 ]────────────────────────────────────────────────────────────────────┐ │ current │ https://confluence.example.com/pages/viewpage.action?pageId=22432553 │ │ bad │ https://confluence.example.com/pages/viewpage.action?pageId=101730306 │ │ good │ https://confluence.example.com/pages/viewpage.action?pageId=101729414 │ └─────────┴───────────────────────────────────────────────────────────────────────┘ |
Still tedious, but not so bad.