Hi All,
On issue creation I need to create a new confluence page from a template that has an attached excel spreadsheet template. I have successfully generated the new page.
I have put our attachment in a blank page, now I need to make a copy of the attachment and attach it to my new page. Each new page needs its own copy of the attachment. So it can't all link to the same page.
I believe I need to do this using the GET to download the attachment and then POST to put the attachment back up. But I am confused as to what exactly is returned by the GET command, and all of the POST examples I see use a File type to upload it.
Here is the code I have, this does not work.. It creates the page but I am not sure how to get the attachment in there.. Do I do it similar to the page creation using a params structure? And where is that documented?
I would appreciate any help
import com.atlassian.applinks.api.ApplicationLink
import com.atlassian.applinks.api.ApplicationLinkService
import com.atlassian.applinks.api.application.confluence.ConfluenceApplicationType
import com.atlassian.jira.issue.Issue
import com.atlassian.sal.api.component.ComponentLocator
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.MutableIssue
import com.atlassian.sal.api.net.Request
import com.atlassian.sal.api.net.Response
import com.atlassian.sal.api.net.ResponseException
import com.atlassian.sal.api.net.ResponseHandler
import groovy.json.JsonBuilder
import groovy.json.JsonSlurper
import groovy.xml.MarkupBuilder
import com.atlassian.sal.api.net.RequestFilePart
import org.apache.log4j.Logger
import org.apache.log4j.Level
def log = Logger.getLogger("com.acme.CreateSubtask")
log.setLevel(Level.DEBUG)
static ApplicationLink getPrimaryConfluenceLink() {
def applicationLinkService = ComponentLocator.getComponent(ApplicationLinkService.class)
final ApplicationLink conflLink = applicationLinkService.getPrimaryApplicationLink(ConfluenceApplicationType.class)
conflLink
}
// the issue provided to us in the binding
def issueManager = ComponentAccessor.getIssueManager()
MutableIssue issue = issueManager.getIssueObject("IT-42")
def confluenceLink = getPrimaryConfluenceLink()
assert confluenceLink // must have a working app link set up
def authenticatedRequestFactory = confluenceLink.createImpersonatingAuthenticatedRequestFactory()
// write storage format using an XML builder
def writer = new StringWriter()
def xml = new MarkupBuilder(writer)
xml.'ac:structured-macro'('ac:name': "jira") {
'ac:parameter'('ac:name': "key", issue.key)
'ac:parameter' ('ac:name': "server", "MY JIRA")
'ac:parameter' ('ac:name': "serverId", "Some server Id")
}
// retrieve contents of "template page"
def confResponse = null
authenticatedRequestFactory
.createRequest(Request.MethodType.GET, "rest/api/content?type=page&title=MY_Template_Page&expand=body.storage.value")
.addHeader("Content-Type", "application/json")
.execute(
new ResponseHandler<Response>()
{
@Override
void handle(Response response) throws ResponseException {
confResponse = new JsonSlurper().parseText(response.getResponseBodyAsString())
}
})
// set the page title - this should be unique in the space or page creation will fail
def pageTitle = issue.key + " Issue Page"
def params = [
type : "page",
title: pageTitle,
space: [
key: "TES" // set the space key - or calculate it from the project or something
],
body : [
storage: [
value : writer.toString() + confResponse.results.body.storage.value[0],
representation: "storage"
]
]
]
authenticatedRequestFactory
.createRequest(Request.MethodType.POST, "rest/api/content")
.addHeader("Content-Type", "application/json")
.setRequestBody(new JsonBuilder(params).toString())
.execute(new ResponseHandler<Response>() {
@Override
void handle(Response response) throws ResponseException {
if (response.statusCode != HttpURLConnection.HTTP_OK) {
throw new Exception(response.getResponseBodyAsString())
} else {
def webUrl = new JsonSlurper().parseText(response.responseBodyAsString)["_links"]["webui"]
log.debug webUrl
}
}
})
def att_file
// hard code the download link for now.
authenticatedRequestFactory
.createRequest(Request.MethodType.GET, "download/attachments/5242908/FM00872.xlsx?version=1&modificationDate=1533302834924&api=v2")
// .addHeader("Content-Type", "application/json")
//.setRequestBody(new JsonBuilder(params).toString())
//.setEntity(entityBuilder.build())
//.setFiles(partList)
.execute(new ResponseHandler<Response>() {
@Override
void handle(Response response) throws ResponseException {
if(response.statusCode != HttpURLConnection.HTTP_OK) {
throw new Exception(response.getResponseBodyAsString())
}
else
{
att_file = new File(response.responseBodyAsString)
}
}
})
// What do I put here? how to I insert what was returned?
authenticatedRequestFactory
.createRequest(Request.MethodType.POST, "rest/api/content/IT-42+MY_Template_Page/child/attachment")
.addHeader("X-Atlassian-Token", "nocheck")
//.setRequestBody(new JsonBuilder(params).toString())
//.setEntity(entityBuilder.build())
//.setFiles(partList)
.execute(new ResponseHandler<Response>() {
@Override
void handle(Response response) throws ResponseException {
if(response.statusCode != HttpURLConnection.HTTP_OK) {
throw new Exception(response.getResponseBodyAsString())
}
}
})
Ok So I never got an answer, but I did get it working.
Here is my code. I create a confluence page and link it to our issue. I added the template as a n attachment to a page in confluence, which is why I can hard code the downlink address, then pull down the excel template and then add the template as an attachment to a my new confluence page. I then add a link to the attachements page inside the jira issue. This way when viewing the issue any user can access the spreadsheet by selecting the link.
I left out the code to create the new page and get the page_id since that code is available in the scriptrunner examples
The trick was to use getResponseAsStream() instead of getResponseAsString() the conversion to string was corrupting the excel file.
import com.atlassian.applinks.api.ApplicationLink
import com.atlassian.applinks.api.ApplicationLinkService
import com.atlassian.applinks.api.application.confluence.ConfluenceApplicationType
import com.atlassian.jira.issue.Issue
import com.atlassian.sal.api.component.ComponentLocator
import com.atlassian.sal.api.net.Request
import com.atlassian.sal.api.net.Response
import com.atlassian.sal.api.net.ResponseException
import com.atlassian.sal.api.net.ResponseHandler
import groovy.json.JsonBuilder
import groovy.json.JsonSlurper
import groovy.xml.MarkupBuilder
import com.atlassian.sal.api.net.RequestFilePart
import org.apache.commons.io.FileUtils
import com.atlassian.jira.issue.link.RemoteIssueLinkBuilder
import com.atlassian.jira.issue.link.RemoteIssueLink
import com.atlassian.jira.issue.link.RemoteIssueLinkManager
import com.atlassian.jira.component.ComponentAccessor
// Get attachment and save to temporary file
def pathName = "C:\\temp\\TEMP.xlsx"
File testfile = new File(pathName);
testfile.createNewFile();
InputStream att_file;
authenticatedRequestFactory
.createRequest(Request.MethodType.GET, "download/attachments/5242908/Workbook.xlsx?version=1&modificationDate=1533302834924&api=v2&download=true")
.addHeader("Content-Type", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
.execute(new ResponseHandler<Response>() {
@Override
void handle(Response response) throws ResponseException {
if(response.statusCode != HttpURLConnection.HTTP_OK) {
throw new Exception(response.getResponseBodyAsString())
}
else
{
att_file = response.getResponseBodyAsStream()
//log.debug "GET " << response.statusCode
}
}
})
FileUtils.copyInputStreamToFile(att_file, testfile);
File fileUpload = new File(pathName)
assert fileUpload
def part = new RequestFilePart(fileUpload, "file")
assert part
def partList = new ArrayList<RequestFilePart>()
partList.add(part)
assert partList
assert partList.size() == 1
//log.debug fileUpload
//log.debug fileUpload.size();
// Add attachment as child
authenticatedRequestFactory
.createRequest(Request.MethodType.POST, "rest/api/content/" + page_id + "/child/attachment")
.addHeader("X-Atlassian-Token", "nocheck")
.setFiles(partList)
.execute(new ResponseHandler<Response>() {
@Override
void handle(Response response) throws ResponseException {
if(response.statusCode != HttpURLConnection.HTTP_OK) {
//log.debug response.statusCode
//log.debug response.getResponseBodyAsString()
throw new Exception(response.getResponseBodyAsString())
}
}
})
def link = "http://yourconfluenceserver:8090/pages/viewpageattachments.action?pageId="+ page_id + "&metadataLink=true"
def customFieldManager = ComponentAccessor.getCustomFieldManager()
def code_field = customFieldManager.getCustomFieldObjectByName("Project Code / Name")
def project_code = issue.getCustomFieldValue(code_field)
def workbook_name = project_code.toString() + " Design Maturity Workbook"
RemoteIssueLinkBuilder remoteIssueLinkBuilder = new RemoteIssueLinkBuilder();
remoteIssueLinkBuilder.issueId(issue.getId());
remoteIssueLinkBuilder.relationship("Link");
remoteIssueLinkBuilder.title(workbook_name.toString());
remoteIssueLinkBuilder.url(link);
RemoteIssueLink remoteIssueLink = remoteIssueLinkBuilder.build();
def user = issue.getAssigneeUser();
Online 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.