Upload attachment using Insight REST API

Chad Peters
Contributor
October 30, 2017

I see the documentation for object attachments but it only specifies GET methods. Is there a means of POSTing attachments via the API?

1 answer

1 accepted

0 votes
Answer accepted
Alexander Sundström
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
October 31, 2017

This should be possible, although I don't have much to go on to help you on this, more then the endpoint to use and what it consumes. So setting this up might be a bit tricky.

/rest/insight/1.0/attachments/object/\{objectid}

Method: POST

 
Path Param                  Type                             Description

objectid                         Integer                          The id of the object where to add the attachment

file                                Collection<FilePart>     The fileparts for the file

encodedComment       FilePart                         The comment for the File

 

Best Regards
Alexander

Chad Peters
Contributor
November 1, 2017

Are you sure that's a supported endpoint? I have tested this multiple ways and can't get it to work. What's interesting, is I can get it to work attaching via REST API to a JIRA, just not to an Insight object. So, I think my POST formatting is correct. 

Below is my code for reference. 

def loadAttachment():

headers = {'Authorization': 'Basic %s' % encoded_credentials.decode("ascii"), 'X-Atlassian-Token' : 'nocheck'}
print('loadAttachmentHeader: ', headers)

files = {'file': open('tmp.txt', 'rb')}
jiraUrl = baseUrl + '/api/latest/issue/BO-17808/attachments'

#Post file to JIRA (this works)#
r = requests.post(jiraUrl, headers=headers, verify=False, files=files)
print(r)


#Post file to Insight object (this doesn't work = 500 error)#
insightUrl = baseURL + '/insight/1.0/attachments/object/2850/'
r = requests.post(insightUrl, headers=headers, verify=False, files=files)
print(r)

Alexander Sundström
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
November 2, 2017

Hi Chad,

Yes, the endpoint I'm referring to is what we use ourself and the signature hasn't changed.

Have you looked at the atlassian-jira.log if it might have logged any errors?

 

Best Regards
Alexander

Chad Peters
Contributor
November 2, 2017

The log is throwing a nullPointerException:

2017-11-02 08:37:09,351 http-nio-9000-exec-19 ERROR daily-jira-s 517x68317x1 pz6y2m 10.2.18.12,10.105.45.11 /rest/insight/1.0/attachments/object/2850 [c.s.j.spi.container.ContainerResponse] Mapped exception to response: 500 (Internal Server Error)
com.riadalabs.jira.plugins.insight.channel.web.api.rest.exception.ServerErrorWebException: java.lang.NullPointerException
at com.riadalabs.jira.plugins.insight.channel.web.api.rest.services.AttachmentResource.addAttachments(AttachmentResource.java:156)

Alexander Sundström
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
November 3, 2017

Hi Chad,

It seems like either the file or the encodedComment is null, could that be the case? Both needs to be provided, and the comment can be empty, but not null.

Best Regards
Alexander 

Chad Peters
Contributor
November 3, 2017

That did it! I was missing the encodedComment. Didn't realize that was required. In case it helps anyone else along the way here's a working version in Python:

 

def loadAttachment():

headers = {'Authorization': 'Basic %s' % encoded_credentials.decode("ascii"), 'X-Atlassian-Token' : 'no-check'}

print('loadAttachmentHeader: ', headers)

multipart_form_data = {
'file': open('tmp.txt', 'rb'),
'encodedComment': ''
}

r = requests.post(insightBaseURL + 'attachments/object/1325', headers=headers, verify=False, files=multipart_form_data)
print(r)
print(r.text)
Chad Peters
Contributor
November 3, 2017

@Alexander Sundström - so close but I'm still having an issue. 

The file appears to be uploaded (shows name, link, bytes, etc.) but when clicked on it's throwing an error. I have manually uploaded the same file as I'm trying to do through the API and the manual file works. When I look at the attachment GET method on the object everything looks the same between the two attachments (below) but only the manual one will open. 

{
"id": 27,
"author": "cpeters",
"mimeType": "application/pdf",
"filename": "InsightQuote.pdf",
"filesize": "16.5 kB",
"created": "03/Nov/17 10:18 AM",
"comment": "file uploaded manually",
"commentOutput": "file uploaded manually",
"url": "https://jira-dev.hbk.com/plugins/servlet/com.riadalabs.jira.plugins.insight/attachment/27/InsightQuote.pdf"
},
{
"id": 28,
"author": "cpeters",
"filename": "InsightQuote.pdf",
"filesize": "16.5 kB",
"created": "03/Nov/17 10:21 AM",
"comment": "file uploaded by shredder",
"commentOutput": "file uploaded by shredder",
"url": "https://jira-dev.hbk.com/plugins/servlet/com.riadalabs.jira.plugins.insight/attachment/28/InsightQuote.pdf"
}

Error:

2017-11-03 10:23:37,838 http-nio-9000-exec-10 ERROR [c.a.j.web.servlet.InternalServerErrorServlet] {errorId=0530a290-29da-4296-98e2-9805c23d811f, interpretedMsg=, cause=java.lang.NullPointerException, stacktrace=java.lang.NullPointerException
at com.opensymphony.module.sitemesh.filter.HttpContentType.<init>(HttpContentType.java:15) [sitemesh-2.5-atlassian-11.jar:?]
at com.opensymphony.sitemesh.compatability.PageParser2ContentProcessor.build(PageParser2ContentProcessor.java:46) [sitemesh-2.5-atlassian-11.jar:?]
at com.opensymphony.sitemesh.webapp.ContentBufferingResponse.getContent(ContentBufferingResponse.java:69) [sitemesh-2.5-atlassian-11.jar:?]
at com.opensymphony.sitemesh.webapp.SiteMeshFilter.obtainContent(SiteMeshFilter.java:183) [sitemesh-2.5-atlassian-11.jar:?]......

Alexander Sundström
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
November 6, 2017

Hi Chad, Thanks for the update, 

From what I can see, when you upload manually you also get the "mimeType": "application/pdf", but that is missing from the one that you upload using the script.

I'm not sure if this is something that is set in the file parts sent to the server or not, but I guess that this is related to the error.

Best Regards
Alexander

Chad Peters
Contributor
November 6, 2017

Thanks. I was actually able to get this all working over the weekend. It was an issue with the multipart content type setup, and more specifically the mime type definition. Below is a (newly) working example for anyone interested and for future reference. 

import mimetypes


def loadAttachment(fileName, fileLocation, objectId):
mimetypes.init()
attachment = fileLocation + fileName
attachmentType = mimetypes.guess_type(attachment, strict=True)

m = MultipartEncoder(
fields={'encodedComment': 'file uploaded by shredder'.encode('utf-8'), 'file': (fileName.replace('\\',''), open(attachment, 'rb'), attachmentType[0])}
)

headers = {'Authorization': 'Basic %s' % encoded_credentials.decode("ascii"), 'X-Atlassian-Token' : 'no-check', 'Content-Type': m.content_type}
r = requests.post(insightBaseURL + 'attachments/object/' + str(objectId), headers=headers, verify=False, data=m)

Like Jon Ringuette likes this
Jon Ringuette
I'm New Here
I'm New Here
Those new to the Atlassian Community have posted less than three times. Give them a warm welcome!
August 25, 2020

Thank you! After several hours of working on this I came across your post which worked wonderfully!

Suggest an answer

Log in or Sign up to answer
TAGS
AUG Leaders

Atlassian Community Events