Come for the products,
stay for the community

The Atlassian Community can help you and your team get more value out of Atlassian products and practices.

Atlassian Community about banner
Community Members
Community Events
Community Groups

Copy attachments to one issue to another with Scriptrunner Cloud

Is it possible to run a post function which creates a subtask and copies all attachments from the parent issue to the subtask; with the obvious restriction that everything is done via the REST APIs? Editmeta for an issue shows that the attachments key has no operations; and that leaves this as the only method for attachment addition. 

I found this answer ( but it relies on copying the file to disk temporarily. I'm assuming that the ScriptRunner Cloud containers do not allow you to do this; or that it would be unreliable for larger files given the 30sec timeout. 

The ideal way would be to simply add attachment IDs from Issue A to Subtask B, but I get the feeling each Issue needs its own copy of an attachment. 

Edit: Fixed link

6 answers

1 accepted

5 votes
Answer accepted

You should be able to clone attachments using the following code in a post function:

import org.apache.http.entity.ContentType;
def createReq ="/rest/api/2/issue")
        .header("Content-Type", "application/json")
            summary: "Cloned issue"

assert createReq.status >= 200 && createReq.status < 300

def clonedIssue = createReq.body

// copy attachments

if (issue.fields.attachment) {
    issue.fields.attachment.collect { attachment ->
        def url = attachment.content as String
        url = url.substring(url.indexOf("/secure"))
        def fileBody = Unirest.get("${url}").asBinary().body
        def resp ="/rest/api/2/issue/${}/attachments")
                .header("X-Atlassian-Token", "no-check")
                .field("file", fileBody, ContentType.create(attachment['mimeType'] as String), attachment['filename'] as String)
        assert resp.status >=200 && resp.status < 300

EDIT: added package import and other code fixes from comments below

Hi @Jon Bevan [Adaptavist], I've tried your code in a post-function on a transition, but I get an error on this line:

def fileBody = Unirest.get("${url}").asBinary().body

body: {"error": "Add-on 'com.onresolve.jira.groovy.groovyrunner' blocked from impersonating the user because the access token does not have the required scope(s)"}
It is running as 'Initiating user'. I also tried running it as add-on user, but then it gives me an error code: status: 401 - Unauthorized
Do you have any idea how to resolve this?



Hi Rudy,

The 401 Unauthorized gives me the impression that the Initiating user might not have permission to view the attachment (or perhaps the issue its attached to).

Thanks, Jon

I'm running it as myself and when I directly go to in my browser the logo loads. So I don't think I have a permission issue from that perspective.

Any other thoughts?

Hi @Jon Bevan [Adaptavist],

I've got ride of the 401 error, by adding the add-on user to the correct project role.

Unfortunately it still does not work.

I get a compile error on: ContentType.create(attachment.mimeType)

Because it is not declared. When I try to import the class with: 

ScriptRunner cannot resolve the class. 

What am I missing here?


Ok, I found out that it was not the correct library to import.

For future reference use:

import org.apache.http.entity.ContentType;

And casting to String will also help

.field("file", fileBody, ContentType.create(attachment['mimeType'] as String), attachment['filename'] as String)

Ciao and thanks Jon for pointing me in the right direction.

Glad you got it working Rudy, and thanks for the correct import - I've updated the code above to reflect your fixes smile

Can this be done in Server as opposed to Cloud?

Hello All,

@Jon Bevan [Adaptavist] 

I need to copy attachments from one of the issue in project to new issue using post function. I am using on-demand jira and have script runner.  Please help me !!!.

Thanks in advance.




Hi Abhi, what have you tried?

Like Abhishek Singh likes this

Hello Jon, 

I got the solution. Thanks 

I have new query if you can help. 

I want to achieve that if the value in checkbox is others then attachment will be mandatory. I am using on-demand instance and have script runner plugin.




Do you mean on a create issue screen? Unfortunately this isn't possible with Jira Cloud.

@Jon Bevan [Adaptavist]  Yes on create screen. If any workaround then please suggest. 



Holding in memory was my initial idea, but I worry about failure when the Script times out if we are looking at larger files (not likely in my use case, but I figure make this a relevant question for people who come back to this question with bigger files)

Also, doesn't the blocking aspect of the HTTP calls prevent you directly streaming from one input call to an output? I would have thought that you would need to do:

Input-A starts=>block execution=>read all the attachments to file/memory=>Input-A Closes

and then

Output-B starts=>block execution=>write all data to stream=>Output-B closes

0 votes
JamieA Rising Star Dec 09, 2016

It should certainly be possible from the perspective of whether the rest apis can do it. I'm not sure if you can write to local disk to be honest, but anyway, you should be able to stream the output of one call to the input of another. Or just hold the entire attachment file in memory. @Jon Mort (Adaptavist) - any ideas?

0 votes

> The ideal way would be to simply add attachment IDs from Issue A to Subtask B, but I get the feeling each Issue needs its own copy of an attachment
You have the right feeling smile. Each issue needs own copy of the attachment.

>  Is it possible to run a post function... with the obvious restriction that everything is done via the REST APIs 

Calling REST API from the post-function looks strange for me. Once you are coding the post-function it's better to rely on JIRA Java API.

Missed the script-runner tag. Apologies. Please refer to Jamie's comment.

Suggest an answer

Log in or Sign up to answer

Atlassian Community Events