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 ?
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);
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
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?
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hi, can you pls share the jar/lib that you used in your program?
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
you save my day, thanks!!
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
I managed to make it work with PostMan.
Header must contain:
Content-Type: multipart/form-data
X-Atlassian-Token: no-check
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).
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Thanks, this worked for me.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hi @Danut M _StonikByte_ , @Ramandeep Singh Nagi ,
I tried to attach the attachment via postman by using your above Info. When I used Content-Type as "multipart/form-data" am getting the below error.
But I removed Content-Type and my postman was successful.
Did I missed anything with "Content-Type" ?
Regards,
Parthiban
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hello Parthiban,
I used the following settings in my Postman:
POST Url:
https://jira.your.url.com/rest/api/latest/issue/ABCD-1234/attachments
Headers:
Content-Type: multipart/form-data,
X-Atlassian-Token: no-check,
charset: UTF-8,
Accept-Encoding: gzip, deflate, br
Body -> form-data:
file: <give path to your file to be attached>
I hope this helps.
Regards,
Ramandeep Singh
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Thanks! Worked like a charm.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
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'));
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Can you please attach the complete file/code?
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
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.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
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.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
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 ?
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
My example has it shown
request.getHeaders().set("X-Atlassian-Token", "no-check");
What is the problem?
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
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 );
}
}
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
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
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
I copy paste the answer from the stackoverflow.comlink, but some dependencies are missing (MultipartEntity, HttpEntity, ...)
Can you help me ?
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
you can download dependencies from here
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
@Loïc GRIVEAU, are you able to attach to issues using sample in stackoverflow link?
if yes then can you sahre your code here?
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
+1
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
@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.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
I've done the other way, by pure "spring-like" flow so to speak.
Actually, I have a complete git project, however, for the attachment, I still need to add functionality, however, I'll give you fast and dirty solution until I add in project.
For details please visit : https://github.com/dobrivoje/jiraintegration
Here is :
REST :
..
@POST
@Consumes(MediaType.MULTIPART_FORM_DATA)
@Produces(MediaType.APPLICATION_JSON)
@Path("createIssueWithAttachment")
ResponseEntity<ResponseIssueCreationDto> createIssueWithAttachmentStreamForSupport(
@FormDataParam("summary") String summary,
@FormDataParam("nmeTeam") @NonNull String nmeTeam,
@FormDataParam("handOverDate") @NonNull Date handOverDate,
@FormDataParam("supportType") @NonNull String supportType,
@FormDataParam("description") String description,
@FormDataParam("siteAddress") String siteAddress,
@FormDataParam("siteContacts") String siteContacts,
@FormDataParam("topology") String topology,
@FormDataParam("file") InputStream attachment,
@FormDataParam("file") FormDataContentDisposition fileDetail,
@FormDataParam("file") FormDataBodyPart body);
...
REST implementation :
@Override
public ResponseEntity<ResponseIssueCreationDto> createIssueWithAttachmentStreamForSupport(
String summary, String nmeTeam,
Date handOverDate, String supportType, String description,
String siteAddress, String siteContacts, String topology,
InputStream attachment,
FormDataContentDisposition fileDetail,
FormDataBodyPart body) {
return ResponseEntity.status( HttpStatus.OK )
.contentType( APPLICATION_JSON )
.body(
service.createNocIssueWithStreamAttachmentForSupport(
supportType, nmeTeam, handOverDate, siteAddress,
siteContacts, topology, description,
summary, attachment, fileDetail, body ) );
}
Custom service (interface) :
ResponseIssueCreationDto createIssueWithStreamAttachmentForSupport(@NonNull String supportType, @NonNull String nmeTeam,
Date handOverDate, String siteAddress,
String siteContacts, String topology,
String description, String summary,
InputStream attachment,
FormDataContentDisposition fileDetail,
FormDataBodyPart body);
Custom service implementation :
@Override
public ResponseIssueCreationDto createIssueWithStreamAttachmentForSupport(String supportType, String nmeTeam,
Date handOverDate, String siteAddress,
String siteContacts, String topology,
String description, String summary,
InputStream attachment,
FormDataContentDisposition fileDetail,
FormDataBodyPart body) {
ResponseIssueCreationDto newIssue = createBasicIssueWithoutAttachmentForSupport(
supportType, nmeTeam, handOverDate, siteAddress, siteContacts, topology, description, summary );
addAttachmentToIssue( attachment, fileDetail, body, newNocIssue.getIssueKey() );
return newNocIssue;
}
@Override
public ResponseIssueCreationDto createBasicIssueWithoutAttachmentForSupport(
String supportType, String nmeTeam, Date handOverDate, String siteAddress,
String siteContacts, String topology, String description, String summary) {
//<editor-fold desc="Stylized error message, for only missing mandatory fields">
boolean isErrSupportType = supportType == null;
boolean isErrNmeTeam = !NocNMETeam.isValidTeam( nmeTeam );
boolean isErrHandOverDate = handOverDate == null;
String errNew = (isErrSupportType ? "Support type, " : "")
+ (isErrNmeTeam ? "NME team, " : "")
+ (isErrHandOverDate ? "Handover date " : "");
String errorMessage = errNew.substring( 0, ((isErrSupportType || isErrNmeTeam) && !isErrHandOverDate) ?
errNew.length() - 2 : errNew.length() ).concat( " must be defined." );
//</editor-fold>
Commons.ensureNonNullsWithMessageFor( errorMessage, supportType, nmeTeam, handOverDate );
//<editor-fold desc="Service desk id, and Request type id">
ServiceDesksDto serviceDeskProjectDto = getAllServiceDesks().orElseThrow( () -> new JiraAllServiceDesksException( errorMessage ) );
ServiceDeskProjectDto sdp = serviceDeskProjectDto
.getValues()
.stream()
.filter( p -> JiraNocProjectKey.equalsIgnoreCase( p.getProjectKey() ) )
.findFirst()
.orElseThrow( () -> new JiraServiceDeskProjectException( errorMessage ) );
String projectIdStr = Optional.ofNullable( sdp.getId() ).orElseThrow( RuntimeException::new );
ServiceDesksRequestTypeDto serviceDesksReqTypeDto = getServiceDeskWithRequestTypeForDesk( Long.valueOf( projectIdStr ) )
.orElseThrow( () -> new JiraServiceDeskRequestTypeException( errorMessage ) );
ServiceDeskRequestTypeValueItemDto srvDesksReqTypeValDto = serviceDesksReqTypeDto
.getValues()
.stream()
.filter( f -> projectIdStr.equals( f.getServiceDeskId() ) )
.filter( n -> JiraNocSupport.equalsIgnoreCase( n.getName() ) )
.findFirst()
.orElseThrow( () -> new JiraServiceDeskRequestTypeValueException( errorMessage ) );
//</editor-fold>
GenericData rootNodeResult = new GenericData();
rootNodeResult.put( ServiceDeskId, projectIdStr );
rootNodeResult.put( RequestTypeId, srvDesksReqTypeValDto.getId() );
GenericData childrenRequestFieldValues = new GenericData();
Date hoDate3BDays = DateUtil.getEndBusinessDayFor( handOverDate, 3 );
String hoDate = new SimpleDateFormat( JIRA_MISTERY_DATETIME_PATTERN2 ).format( hoDate3BDays );
childrenRequestFieldValues.put( REQIRED_BY_DATE, hoDate );
childrenRequestFieldValues.put( SITE_ADDRESS, Commons.getFieldWithValidLengthOf255( siteAddress ) );
childrenRequestFieldValues.put( SITE_CONTACTS, siteContacts );
childrenRequestFieldValues.put( TOPOLOGY, topology );
childrenRequestFieldValues.put( SUMMARY, summary );
childrenRequestFieldValues.put( DESCRIPTION, description );
GenericData childReqNMETeam = new GenericData();
try {
childReqNMETeam.put( "value", NocNMETeam.getValidCode( nmeTeam ) );
childrenRequestFieldValues.put( NME_TEAM, childReqNMETeam );
} catch (UnsupportedOperationException nte) {
throw new JiraNOCTeamException( NocNMETeam.getValidTeams(), JIRA_HOME_URL, JiraNocReqCustPortalId, JiraNocReqCustomerPortalCreateId );
}
GenericData childReqSupportType = new GenericData();
try {
childReqSupportType.put( "value", NocSupportType.getValidCodeFor( supportType ) );
childrenRequestFieldValues.put( SUPPORT_TYPE, childReqSupportType );
} catch (UnsupportedOperationException nst) {
throw new JiraNOCSupportTypeException( NocSupportType.getValidTypes(), JIRA_HOME_URL, JiraNocReqCustPortalId, JiraNocReqCustomerPortalCreateId );
}
rootNodeResult.put( RequestFieldValues, childrenRequestFieldValues );
return jiraClient.executeBasicPost( ResponseIssueCreationDto.class, apiCallIssueCreateByRequestType, rootNodeResult, true );
}
This is what you actually need :
@Override
public List<ResponseItemAttachmentDto> addAttachmentToIssue(InputStream inputStream, FormDataContentDisposition fileDetail,
FormDataBodyPart body, @NonNull String issueKey) {
String urlParamCall = MessageFormat.format( jiraAddAttachmentToIssueKey, issueKey );
GenericData rootNodeResult = new GenericData();
rootNodeResult.put( ATTACHMENT, new AttachmentInfoHolderDto( inputStream, fileDetail, body ) );
GenericData headers = new GenericData();
headers.put( "X-Atlassian-Token", "no-check" );
return jiraClient.executePostExpectingList( ResponseItemAttachmentDto.class, urlParamCall,
headers, rootNodeResult, true );
}
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hello, just facing problem with UTF-8 characters in file name.
When uploading with postman, like in example everything is fine, but when uploading by java API, german umalut characters are converted as ????
Any suggestion?
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Here's a working method from a Python 3.x module. The key things that aren't spelled out in many solutions:
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
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
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");
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
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
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Awesome. This worked perfectly..
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Where is the ticket URL
?
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Sorry I posted this answer more than 3 years back, I don't remember anything as of now
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
if you want to do it through perl then try with this
https://metacpan.org/pod/JIRA::Client::Automated#attach_file_to_issue
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Atlassian Government Cloud has achieved FedRAMP Authorization at the Moderate level! Join our webinar to learn how you can accelerate mission success and move work forward faster in cloud, all while ensuring your critical data is secure.
Register NowOnline forums and learning are now in one easy-to-use experience.
By continuing, you accept the updated Community Terms of Use and acknowledge the Privacy Policy. Your public name, photo, and achievements may be publicly visible and available in search engines.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.