Forums

Articles
Create
cancel
Showing results for 
Search instead for 
Did you mean: 

Unable to attach large file via REST API

Hari May 29, 2024

Hi All,

I'm using below REST API to attach files to JIRA using powershell script.

rest/api/2/issue/808569/attachments

 

I'm able to upload files up to 8kb , but files greater than 8kb getting '403 forbidden" error.

I have not done any changes to the credentials, its the same script only the file path is changed.

Manually I'm able to upload files greater than 100mb but via API I'm not able upload more than 8kb. 

Additionally via POSTMAN I'm able to attach files of any size, only through powershell facing this issue.

 

Is there any configuration to increase the limit ? or any other suggestion? 

1 answer

1 accepted

0 votes
Answer accepted
Rudy Holtkamp
Community Champion
May 29, 2024

Hi @Hari & Welcome to the community,

Could you post your full code?

Did you check the REST API documentation of the attachments? And did you include the header: 

-H "X-Atlassian-Token: nocheck" 

Here you can find an example which is for server/datacenter: https://confluence.atlassian.com/jirakb/how-to-add-an-attachment-to-a-jira-issue-using-rest-api-699957734.html 

 

 

Hari May 29, 2024

Hi @Rudy Holtkamp 

Below is my code --> I have masked username/password and url for security concerns.  

# Define username and password
$username = "XYZ"
$password = "XYZ"
# Encode the username and password for basic authentication
$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes("${username}:${password}"))
# Define the headers including the Authorization header
$headers = @{
"X-Atlassian-Token" = "nocheck"
"Authorization" = "Basic $base64AuthInfo"
}
# Define the file to be uploaded
$filePath = "XYZ"

# Ensure the file exists
if (-Not (Test-Path $filePath)) {
Write-Host "File does not exist."
exit
}
# Create a boundary for the multipart/form-data
$boundary = [System.Guid]::NewGuid().ToString()
$lf = "`r`n"
# Create the multipart content manually
$bodyLines = @(
"--$boundary",
"Content-Disposition: form-data; name=`"file`"; filename=`"$([System.IO.Path]::GetFileName($filePath))`"",
"Content-Type: application/octet-stream",
"",
[System.IO.File]::ReadAllText($filePath, [System.Text.Encoding]::Default),
"--$boundary--"
) -join $lf
# Convert the body to bytes
$bodyBytes = [System.Text.Encoding]::Default.GetBytes($bodyLines)
# Invoke the web request to upload the file
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
try {
$response = Invoke-WebRequest -Uri "https://jira.com/rest/api/2/issue/808569/attachments"`
-Method Post `
-Headers $headers `
-ContentType "multipart/form-data; boundary=$boundary" `
-Body $bodyBytes `
-Verbose
Write-Host "Response: $($response.Content)"
} catch {
Write-Host "Error: $_"
}

 

 

The above code works fine when i upload files below 8kb, above that i get "403 forbidden" error.

 

Any help to resolve above issue would be appreciated.

Rudy Holtkamp
Community Champion
May 30, 2024

The issue with your code likely stems from how the file content is being read and converted into the body of the multipart/form-data request. Specifically, using [System.IO.File]::ReadAllText reads the entire file as a single string. This approach can run into limitations and may not handle binary data correctly, leading to issues with larger files or files containing non-text data.

Here's a revised version of your script that correctly handles file content as binary data:

# Define username and password
$username = "XYZ"
$password = "XYZ"

# Encode the username and password for basic authentication
$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes("${username}:${password}"))

# Define the headers including the Authorization header
$headers = @{
    "X-Atlassian-Token" = "nocheck"
    "Authorization"     = "Basic $base64AuthInfo"
}

# Define the file to be uploaded
$filePath = "XYZ"

# Ensure the file exists
if (-Not (Test-Path $filePath)) {
    Write-Host "File does not exist."
    exit
}

# Create a boundary for the multipart/form-data
$boundary = [System.Guid]::NewGuid().ToString()
$lf = "`r`n"

# Read the file content as bytes
$fileBytes = [System.IO.File]::ReadAllBytes($filePath)

# Create the multipart content manually
$bodyLines = @(
    "--$boundary",
    "Content-Disposition: form-data; name=`"file`"; filename=`"$([System.IO.Path]::GetFileName($filePath))`"",
    "Content-Type: application/octet-stream",
    "",
    [System.Convert]::ToBase64String($fileBytes),
    "--$boundary--"
) -join $lf

# Convert the body to bytes
$bodyBytes = [System.Text.Encoding]::ASCII.GetBytes($bodyLines)

# Invoke the web request to upload the file
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
try {
    $response = Invoke-WebRequest -Uri "https://jira.com/rest/api/2/issue/808569/attachments" `
        -Method Post `
        -Headers $headers `
        -ContentType "multipart/form-data; boundary=$boundary" `
        -Body $bodyBytes `
        -Verbose
    Write-Host "Response: $($response.Content)"
}
catch {
    Write-Host "Error: $_"
}
Hari May 30, 2024

Hi @Rudy Holtkamp ,

 

I executed above code and ran into same "403 forbidden" error. Please find below error.

 

Invoke-WebRequest : 403 Forbidden
At line:1 char:13
+ $response = Invoke-WebRequest -Uri "https://itsm-servicedesk.temenos. ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:Htt
pWebRequest) [Invoke-WebRequest], WebException
+ FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShe
ll.Commands.InvokeWebRequestCommand

 

However the above code is working fine for file size less than 8kb.

 

Rudy Holtkamp
Community Champion
May 30, 2024

Ok, that is odd. I'm thinking more and more that is, is a proxy issue.

But before you go there, could you check if you can upload the issues with a Python script?

from atlassian import Jira
import os

# Set your Jira credentials and server URL
JIRA_URL = 'https://your-jira-instance.com'
JIRA_USERNAME = 'your-email@example.com'
JIRA_API_TOKEN = 'your-api-token'

# Initialize the Jira object
jira = Jira(
url=JIRA_URL,
username=JIRA_USERNAME,
password=JIRA_API_TOKEN
)

# Function to upload multiple attachments to a JIRA issue
def upload_attachments(issue_key, attachment_paths):
for attachment_path in attachment_paths:
if os.path.isfile(attachment_path):
try:
with open(attachment_path, 'rb') as file:
response = jira.issue_add_attachment(issue_key, file)
if response.status_code == 200:
print(f"Successfully uploaded {attachment_path} to {issue_key}")
else:
print(f"Failed to upload {attachment_path} to {issue_key}, status code: {response.status_code}")
except Exception as e:
print(f"An error occurred while uploading {attachment_path}: {str(e)}")
else:
print(f"File {attachment_path} does not exist")

# Example usage
if __name__ == "__main__":
issue_key = 'PROJECT-123'
attachment_paths = [
'/path/to/attachment1.txt',
'/path/to/attachment2.jpg',
'/path/to/attachment3.pdf'
]

upload_attachments(issue_key, attachment_paths)

First install python then use 'pip install atlassian-python-api' to get the atlassain lib.

If this does not work, then it is something in your network that is blocking larger files.

Hari May 30, 2024

Hi @Rudy Holtkamp ,

 

Thanks for the Python code.

Executed the Python code and got the same error "403 Client Error: Forbidden for url" .

 

But the Python code is working for file size less than 8kb, same as Powershell

Rudy Holtkamp
Community Champion
May 30, 2024

Then it is for sure something in the network. I would start by looking at the proxy server. 

Hari May 31, 2024 edited

Hi @Rudy Holtkamp ,

 

EUREKA!! EUREKA!! Finally found the solution to the issue.

As I mentioned in my above issue description that I was able to attach files of any size via POSTMAN but not via POWERSHELL script. 

So I started to dig deeper in that direction and tried to compare the request that was being sent by POSTMAN and my POWERSHELL script. 

On comparing the request sent by POSTMAN and my POWERSHELL script, there was this below highlighted header, which was missing in my request. Adding it to my POWERSHELL code resolved the issue. 

Please find below updated working code.

 

# Define username and password
$username = "XYZ"
$password = "XYZ"
# Encode the username and password for basic authentication
$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes("${username}:${password}"))
# Define the headers including the Authorization header
$headers = @{
"X-Atlassian-Token" = "nocheck"
"Authorization" = "Basic $base64AuthInfo"
"Transfer-Encoding" = "chunked"

}
# Define the file to be uploaded
$filePath = "XYZ"
# Ensure the file exists
if (-Not (Test-Path $filePath)) {
Write-Host "File does not exist."
exit
}
# Create a boundary for the multipart/form-data
$boundary = [System.Guid]::NewGuid().ToString()
$lf = "`r`n"
# Create the multipart content manually
$bodyLines = @(
"--$boundary",
"Content-Disposition: form-data; name=`"file`"; filename=`"$([System.IO.Path]::GetFileName($filePath))`"",
"Content-Type: multipart/form-data",
"",
[System.IO.File]::ReadAllText($filePath, [System.Text.Encoding]::Default),
"--$boundary--"
) -join $lf
# Convert the body to bytes
$bodyBytes = [System.Text.Encoding]::Default.GetBytes($bodyLines)
# Invoke the web request to upload the file
try {
$response = Invoke-WebRequest -Uri "https://jira.com/rest/api/2/issue/1234/attachments"`
-Method Post `
-Headers $headers `
-ContentType "multipart/form-data; boundary=$boundary" `
-Body $bodyBytes `
-Verbose
Write-Host "Response: $($response.Content)"
} catch {
Write-Host "Error: $_"
}


Not sure how I can add this header to the python code which you shared. Would be helpful if you send the updated Python code in which we can include the above header.

 

Thanks much for the help though!! 

Kudos!!

 

Suggest an answer

Log in or Sign up to answer
TAGS
atlassian, likes for trees, atlassian community, social impact, tree planting campaign, community kudos, atlassian giving, environmental impact, sustainability, likes for good, atlassian social responsibility, community challenge

Make every click count—help us plant 50,000 trees! 🌳

Want to make your everyday Community actions directly contribute to reforestation? The Atlassian Community can achieve this goal by liking a post, attending an ACE, sending your peers kudos, and so much more!

Help us plant more trees
AUG Leaders

Atlassian Community Events