It's not the same without you

Join the community to find out what other Atlassian users are discussing, debating and creating.

Atlassian Community Hero Image Collage

How do I upload attachment to JIRA Issue via REST API?

Is it possible to upload attachment in java using REST API without using cURL ?

Is it possible to upload a file using REST API BROWSER ?

9 answers

1 accepted

6 votes
Answer accepted

Here my code for upload and download attachment :

public boolean addAttachmentToIssue(String issueKey, String fullfilename) throws IOException{

		CloseableHttpClient httpclient = HttpClients.createDefault();
		
		HttpPost httppost = new HttpPost(jira_attachment_baseURL+"/api/latest/issue/"+issueKey+"/attachments");
		httppost.setHeader("X-Atlassian-Token", "nocheck");
		httppost.setHeader("Authorization", "Basic "+jira_attachment_authentication);
		
		File fileToUpload = new File(fullfilename);
		FileBody fileBody = new FileBody(fileToUpload);
		
		HttpEntity entity = MultipartEntityBuilder.create()
				.addPart("file", fileBody)
				.build();
		
		httppost.setEntity(entity);
        String mess = "executing request " + httppost.getRequestLine();
        logger.info(mess);
        
        CloseableHttpResponse response;
		
        try {
			response = httpclient.execute(httppost);
		} finally {
			httpclient.close();
		}
        
		if(response.getStatusLine().getStatusCode() == 200)
			return true;
		else
			return false;

	}
	
	public boolean getAttachmentFromIssue(String contentURI, String fullfilename) throws IOException {
        
		CloseableHttpClient httpclient = HttpClients.createDefault();
        
        try {
            HttpGet httpget = new HttpGet(contentURI);
            httpget.setHeader("Authorization", "Basic "+jira_attachment_authentication);
                        
            System.out.println("executing request " + httpget.getURI());

            CloseableHttpResponse response = httpclient.execute(httpget);
            
            int status = response.getStatusLine().getStatusCode();
            if (status >=200 && status < 300) {
            	HttpEntity entity = response.getEntity();
            	if (entity.isStreaming()) {
            		byte data[] = EntityUtils.toByteArray(entity);
            		FileOutputStream fout = new FileOutputStream(new File(fullfilename));
            		fout.write(data);
            		fout.close();
            	}
            }
		} finally {
            httpclient.close();
        }
        
        return true;
	}

jira_attachment_authentication is define elsewhere as :

jira_attachment_authentication = new String(org.apache.commons.codec.binary.Base64.encodeBase64((user+":"+pass).getBytes()));

Can you show me your which is getting the file? File fileToUpload = new File(fullfilename); FileBody fileBody = new FileBody(fileToUpload);

Loïc GRIVEAU, if I try to use the same code to move attachments from one JIRA instance to another, it gives 415 error. : 415 Unsupported Media Type.

 

Any idea?

Like # people like this

Hi, can you pls share the jar/lib that you used in your program?

you save my day, thanks!!

I managed to make it work with PostMan.

Header must contain:

Content-Type: multipart/form-data

X-Atlassian-Token: no-check 

PM_Headers.jpg

Body must be of type "form-data" and must contain a key named "file" with value a specified file (I had to use the file picker, see the picture).

PM_Body.jpg

Thanks, this worked for me.

This works for me:

 

  const auth = 'Basic ' + new Buffer(props['jiraAppUserName'] + ':' + props['jiraAppPassword']).toString('base64');
var options = {
url: 'https://JIRAUAT.xx.xx/rest/api/latest/issue/XEA-1255/attachments',
headers: {
'Authorization': auth,
'X-Atlassian-Token': 'nocheck'
}
};

var r = request.post(options, function (err, res, body) {
if (err) {
console.error(err);
resOut.status(500).json({
messages: 'outch',
obj: {}
});
} else {
console.log('Upload successful! Server responded with:', body);
resOut.status(200).json({
messages: 'successfully updated jira ticket',
obj: {}
});
}
}
);

var form = r.form();
form.append('file', fs.createReadStream('./somefile.png'));

 

Can you please attach the complete file/code?

Like Ian Keller likes this

Yes it's possible. For example JIRA REST Java Client does that: https://bitbucket.org/atlassian/jira-rest-java-client/src/bd758b52f53978033bdd0d8071edd75d7bdcc607/core/src/main/java/com/atlassian/jira/rest/client/internal/async/AsynchronousIssueRestClient.java?at=master#

You'll have to send multipart request - the code will depend on HTTP client that you use.

There is already answer for that question here: http://stackoverflow.com/questions/18631361/add-attachment-to-jira-via-rest-api

I copy paste the answer from the stackoverflow.comlink, but some dependencies are missing (MultipartEntity, HttpEntity, ...)

Can you help me ?

you can download dependencies from here

http://hc.apache.org/downloads.cgi

@Loïc GRIVEAU, are you able to attach to issues using sample in stackoverflow link?

if yes then can you sahre your code here?

@Aleksander Mierzwicki, is there a way we can copy ALL attachments from one JIRA issue in one server to another JIRA issue in another server? I have been trying all the code snippets given for this question and am getting 415 Unsupported media type error.

HttpRequestFactory requestFactory = new NetHttpTransport().createRequestFactory(parameters);

MultipartContent content = new MultipartContent().setMediaType(
new HttpMediaType("multipart/form-data").setParameter("boundary", "__END_OF_PART__"));


for(Attachment attachment : attachments) {
File attachmentFile = ComponentAccessor.getAttachmentManager().
streamAttachmentContent(attachment, new FileInputStreamConsumer(attachment.getFilename()));

String mimeType = URLConnection.guessContentTypeFromName(attachmentFile.getName());

FileContent fileContent = new FileContent(mimeType, attachmentFile);
MultipartContent.Part part = new MultipartContent.Part(fileContent);
part.setHeaders(new HttpHeaders().set(
"Content-Disposition",
String.format("form-data; name=\"file\"; filename=\"%s\"", attachmentFile.getName())));
content.addPart(part);
}


HttpRequest request = requestFactory.buildPostRequest(jiraUrl, content);
request.getHeaders().set("X-Atlassian-Token", "no-check");
return request.execute();

Java code using google-http to POST attachments to /rest/api/2/issue/{issueIdOrKey}/attachments using OAuth. Still trying to figure out format for posting attachments on issue create.

What will be body for this endpoint i am using postman and it is not working for me : /rest/api/2/issue/{issueIdOrKey}/attachments

can anyone share postman body.

neither for me.... i have try all :(

Hi guys ! I've managed to POST attachment via Postman. An example :
https://jira-dev.server_url.com/rest/api/2/issue/NOC-618/attachments
Everything works fine.

However, I need to implement via Java service which use OAuth1.
First, there is a need to manipulate header, that is, to insert

"X-Atlassian-Token", "no-check"

and then, to upload actual input streams.

Any ideas ?

My example has it shown 

request.getHeaders().set("X-Atlassian-Token", "no-check");

What is the problem? 

Hi ! Thanks for a quick response !
Well, I've done authentication via OAuth, from a Jira tutorial, and have this method for post request, and i don't know how to manipulate header :

public HttpResponse executePrimitivePostRequest(@NonNull String url, @NonNull GenericData contentGenericData) {
String apiCallUrlPath = JIRA_HOME_URL + url;

try {
OAuthParameters parameters = jiraOAuthClient.getParameters( JIRA_ACCESS_TOKEN, JIRA_SECRET_KEY, JIRA_CONSUMER_KEY, JIRA_PRIVATE_KEY );
HttpContent content = new JsonHttpContent( new JacksonFactory(), contentGenericData );
HttpResponse response = postResponseFromUrl( parameters, new GenericUrl( apiCallUrlPath ), content );

return response;
} catch (HttpResponseException hre) {
String errMsg = "Executing Post Request Error. " + hre;
LOGGER.log( Level.SEVERE, errMsg, hre );
throw new RuntimeException( errMsg, hre );
} catch (Exception e) {
String errMsg = "Executing Get Request, no result.";
LOGGER.log( Level.INFO, errMsg, e );
throw new RuntimeException( errMsg, e );
}
}

if you want to do it through perl then try with this

https://metacpan.org/pod/JIRA::Client::Automated#attach_file_to_issue

THIS CODE WORKS:

 

public class JiraRest {

public static void main(String[] args) throws ClientProtocolException, IOException
{
String pathname= "<Full path name of the attachment file>";
File fileUpload = new File(pathname);

HttpClient httpClient = HttpClientBuilder.create().build();
HttpPost postRequest = new HttpPost("URL+Post REST API");
BASE64Encoder base=new BASE64Encoder();
String encoding = base.encode ("username:password".getBytes());
postRequest.setHeader("Authorization", "Basic " + encoding);
postRequest.setHeader("X-Atlassian-Token","nocheck");

MultipartEntityBuilder entity=MultipartEntityBuilder.create();
entity.addPart("file", new FileBody(fileUpload));
postRequest.setEntity( entity.build());
HttpResponse response = httpClient.execute(postRequest);
}
}


Required JARs:

All JARs in lib folder of httpcomponents-client-4.5-bin and sun.misc.BASE64Decoder.jar

Awesome. This worked perfectly..

Where is the ticket URL

?

Sorry I posted this answer more than 3 years back, I don't remember anything as of now 

HttpPost postRequest = new HttpPost("URL+Post REST API");

does this mean like this

HttpPost postRequest = new HttpPost("https:/abc.atlassian.net/rest/api/2/issue+https://abc.atlassian.net/browse/MSAM-42?filter=-4");

Here's a working method from a Python 3.x module. The key things that aren't spelled out in many solutions:

  • all file data must be read as binary data, even plain text files
  • the multipart boundary string need not be anything fancy, but it must be a string that is unlikely to occur in the file data
  • multipart lines are separated by Carriage Return + Line Feed
  • all the multipart strings must be converted to binary, then wrapped around the binary file contents
  • when calculating "Content-Length", take the length of the entire multipart form, not just the length of the file contents
def add_attachment(self, path):
    '''Upload a file attachment from a local file path.
    '''
    error_messages = []
    try:
        f = open(path, 'rb'# all files, even plain text, must be read as binary data
        file_contents = f.read()
        f.close()
    except:
        error_messages.append('cannot read ' + path)

    if not error_messages:
        # create multipart/form-data as defined in RFC 1867 (see: https://www.ietf.org/rfc/rfc1867.txt)
        boundary = binascii.hexlify(os.urandom(16)).decode('ascii')
        separator = '\r\n' # CRLF is the standard separator in multipart/form-data
        # multipart/form-data consists of: prefix + file contents + suffix
        prefix = '--{}{}'.format(boundary, separator)
        prefix += 'Content-Disposition: form-data; name="file"; filename="{}"{}'.format(os.path.basename(path), separator)
        prefix += 'Content-Type: application/octet-stream{}'.format(separator)
        prefix += separator
        suffix = separator + '--{}--{}'.format(boundary, separator)

        # convert the prefix and suffix text to binary, and then join them around the binary file contents
        prefix = prefix.encode('utf-8')
        suffix = suffix.encode('utf-8')
        data = b''.join([prefix, file_contents, suffix])

        headers = {}
        headers['Content-Type'] = 'multipart/form-data; boundary={}'.format(boundary)
        headers['X-Atlassian-Token'] = 'no-check'
        headers['Content-Length'] = str(len(data)) # length must include the entire multipart/form-data, not just the file contents

        api = 'api/2/issue/' + self.key + '/attachments'
        (status, response) = self._session._call_api(api, headers=headers, data=data)
        if not (status >= 200 and status <= 299):
            error_messages += standard_errors(status, response)

    return error_messages

 

Hello;

Do you have sample code for downloading all attachments of all Jira issues reported in a Jira project? 

Thank you;

Lily

Suggest an answer

Log in or Sign up to answer
TAGS

Community Events

Connect with like-minded Atlassian users at free events near you!

Find an event

Connect with like-minded Atlassian users at free events near you!

Unfortunately there are no Community Events near you at the moment.

Host an event

You're one step closer to meeting fellow Atlassian users at your local event. Learn more about Community Events

Events near you