# system.net.httpClient file parameter for Jira attachment

**URL:** <https://forum.inductiveautomation.com/t/system-net-httpclient-file-parameter-for-jira-attachment/65692>\
**Category:** Ignition\
**Tags:** ignition81, perspective\
**Created:** [October 26, 2022, 6:30am UTC](https://forum.inductiveautomation.com/t/system-net-httpclient-file-parameter-for-jira-attachment/65692 "2022-10-26T06:30:52Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![guillaume.voisin](https://avatars.discourse-cdn.com/v4/letter/g/bcef8e/32.png) [@guillaume.voisin](https://forum.inductiveautomation.com/u/guillaume.voisin)\
**Post date:** [October 26, 2022, 6:30am UTC](https://forum.inductiveautomation.com/t/system-net-httpclient-file-parameter-for-jira-attachment/65692/1 "2022-10-26T06:30:52Z")

</div>

Hi,  
I'm trying to post attachment to Jira Sofware Cloud using system.net.httpClient

Jira documentation :  
([https://developer.atlassian.com/cloud/jira/platform/rest/v3/api-group-issue-attachments/#api-rest-api-3-issue-issueidorkey-attachments-post](https://developer.atlassian.com/cloud/jira/platform/rest/v3/api-group-issue-attachments/#api-rest-api-3-issue-issueidorkey-attachments-post))

I'm using the following code :

```
def addAttachment(domain, filepath, issue, user, passwd):
baseurl	= "https://" + domain + "/" + str(issue) + "/attachments"

headers = {
   "Accept": "application/json",
   "X-Atlassian-Token": "no-check",
}

payload = filepath

client = system.net.httpClient()
response = client.post(baseurl, username=user, password=passwd, file=payload, headers=headers)

if response.good:
	return str(response) + " | " + response.text
else :
	return str(response) + " | " + response.text

```

resulting in the following error :

> ..atlassian.net/rest/api/3/issue/10334/attachments' [400]\> | {"message":"org.apache.commons.fileupload.FileUploadBase$InvalidContentTypeException: the request doesn't contain a multipart/form-data or multipart/mixed stream, content type header is application/octet-stream","status-code":500,"stack-trace":""}

It seems like the file parameter is not fully compliant with what Jira is waiting for.

Could you help me solving this issue ?

Thank you in advance

Guillaume

---

<div class="post-metadata">

**Author:** ![Transistor](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/transistor/32/3380_2.png) [@Transistor](https://forum.inductiveautomation.com/u/Transistor)\
**Post date:** [October 26, 2022, 6:37am UTC](https://forum.inductiveautomation.com/t/system-net-httpclient-file-parameter-for-jira-attachment/65692/2 "2022-10-26T06:37:26Z")

</div>

Tip: use the \</\> code formatting button to preserve code indentation and apply syntax highlighting. It's essential for Python and makes any code much easier to read. There's an edit button 🖉 below your post so you can fix it.

---

<div class="post-metadata">

**Author:** ![paul-griffith](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/paul-griffith/32/37249_2.png) [@paul-griffith](https://forum.inductiveautomation.com/u/paul-griffith)\
**Post date:** [October 26, 2022, 3:38pm UTC](https://forum.inductiveautomation.com/t/system-net-httpclient-file-parameter-for-jira-attachment/65692/3 "2022-10-26T15:38:37Z")

</div>

`httpClient` doesn't currently have any builtin support for form data requests, unfortunately.

You'll have to manually create the data in the appropriate 'shape' - basically, write out the required header and then append the encoded attachment data, and set the Content-Type header manually.

---

<div class="post-metadata">

**Author:** ![S\_ANIL\_KUMAR](https://avatars.discourse-cdn.com/v4/letter/s/898d66/32.png) [@S\_ANIL\_KUMAR](https://forum.inductiveautomation.com/u/S_ANIL_KUMAR)\
**Post date:** [September 28, 2023, 5:02pm UTC](https://forum.inductiveautomation.com/t/system-net-httpclient-file-parameter-for-jira-attachment/65692/4 "2023-09-28T17:02:12Z")

</div>

Hi,  
May i know if you were able to add attachments from ignition to a jira issue, I constructed the request body and was able to add attachments that were less than 50kb but attachments that are above 50kb, throws an error saying bad gateway 502.

Could you share your thoughts on this.

---

<div class="post-metadata">

**Author:** ![guillaume.voisin](https://avatars.discourse-cdn.com/v4/letter/g/bcef8e/32.png) [@guillaume.voisin](https://forum.inductiveautomation.com/u/guillaume.voisin)\
**Post date:** [October 2, 2023, 8:17am UTC](https://forum.inductiveautomation.com/t/system-net-httpclient-file-parameter-for-jira-attachment/65692/5 "2023-10-02T08:17:56Z")

</div>

Hi @S_ANIL_KUMAR,

I was able to post attachments from Ignition.  
My issue was for attachements that were over 64 Kb.

First, I changed the code of \_socket.py (located in C:\Program Files\Inductive Automation\Ignition\user-lib\pylib on my server).  
Changed the line 1207 :

```auto
    sendall = send # FIXME see note above!

```

by :

```auto
def sendall(self, data, flags=0):
        chunk_size = 8192
        length = len(data)
        data_view = memoryview(data)
        idx = 0
        while idx < length:
            bytes_sent = self.send(data_view[idx:idx + chunk_size], flags=flags)
            idx += bytes_sent

```

Then, I built the code below (I used some classes but you can simplify it as you need) :

```auto
from abc import ABCMeta, abstractmethod

# Abstract class -- do not instanciate
class JiraObject():
	__metaclass__ = ABCMeta
	
	baseUrl = "https://*.atlassian.net/rest/api/3/"
	username = "username"
	token = "apitoken" 
	proxyUrl = "proxyUrl"
	
	@abstractmethod
	def __init__ (self):
		self.id = None
		
	def __getAuthToken__ (self):
		from requests.auth import HTTPBasicAuth
		
		return HTTPBasicAuth(self.username, self.token)
		
	def __getProxy__ (self):
		return {"https" :self.proxyUrl}
		
	def get(self):
		pass
		
	def post(self):
		pass

# Abstract class -- do not instanciate
class Issue(JiraObject):
	
	@abstractmethod
	def __init__ (self, summary, description, project, issueType):
		JiraObject. __init__ (self)
		self.summary = summary
		self.description = description
		self.project = project
		self.issueType = issueType
	
	def toString(self):
		import json
		issue = {"fields": 
					{ "summary"	: self.summary,
				    	"project"	: {"key"	: self.project},
					    "issuetype"	: {"name"	: self.issueType}
				    }
				}
		return json.dumps(issue)
	
	def get(self):
		pass
	
	def post(self):
		pass

class Bug(Issue):

	def __init__ (self, summary, description, project, issueType="Bug"):
		Issue. __init__ (self, summary, description, project, issueType)
		
	def post(self, filePath=None):
		import requests
		import json
		
		url = self.baseUrl + "issue"
		
		headers = {"Accept": "application/json", "Content-Type": "application/json"}
		
		with requests.request("POST", url, headers=headers, proxies=self. __getProxy__ (), auth=self. __getAuthToken__ (), verify=False, data=self.toString()) as response :
			if response.ok:
				self.id = json.loads(response.text)["id"] 
				if filePath != None :
					attach = self. __addAttachment__ (filePath)
					if attach != None :
						return self.id
					else:
						return "attach " + str(attach)
				else :
					return self.id
			else:
				return "pb >> " + response.text
	
	def __addAttachment__ (self, filePath):
		import requests
		
		url = self.baseUrl + "issue/" + str(self.id) + "/attachments"
	
		headers = {'Accept': 'application/json', 'X-Atlassian-Token': 'no-check', "Accept-Encoding":"deflate"}
			
		with open(filePath, "rb") as f:
			files= {"file": ("capture.png", f, "application-type")}
			with requests.request("POST", url, headers=headers, files=files, proxies=self. __getProxy__ (), auth=self. __getAuthToken__ (), verify=False) as response
			if response.ok :
				return str(response), str(response.text)
			else :
				return "ko" + response.text

```

Let me know if it helps 🙂

---

<div class="post-metadata">

**Author:** ![S\_ANIL\_KUMAR](https://avatars.discourse-cdn.com/v4/letter/s/898d66/32.png) [@S\_ANIL\_KUMAR](https://forum.inductiveautomation.com/u/S_ANIL_KUMAR)\
**Post date:** [October 3, 2023, 5:35am UTC](https://forum.inductiveautomation.com/t/system-net-httpclient-file-parameter-for-jira-attachment/65692/6 "2023-10-03T05:35:46Z")

</div>

Hi @guillaume.voisin , I did change the line1207 in the \_socket.py file. But I don't see any difference in the result. As I am using the httplib/urrlib2 module to send post requests.  
I've constructed a request body to add the attachment for a particular jira issue. May I know what should be corrected to add attachments that are above 50kb.(mp4, jpeg etc.)

from base64 import b64encode  
import os  
import urllib2  
from org.python.core import PyByteArray

jira\_url = "[https://domain-name/rest/api/2/issue/{issueID}/attachments](https://domain-name/rest/api/2/issue/%7BissueID%7D/attachments)"  
username = "[email.com](http://email.com/)"  
api\_token = "api\_token"  
auth =b64encode(username +":"+api\_token)

file\_path = system.file.openFile()  
file\_data =system.file.readFileAsBytes(file\_path)

# Prepare the request

request = urllib2.Request(jira\_url)  
boundary = "----" + "UniqueBoundaryArray"  
request.add\_header("Content-Type", "multipart/form-data; boundary={}".format(boundary))

# Encode credentials for basic authentication

request.add\_header("Authorization", "Basic {}".format(auth))  
request.add\_header("X-Atlassian-Token","no-check")

# Build the request body

body = b''  
body += b"--" + boundary + b"\r\n"  
body += b"Content-Disposition: form-data; name="file"; filename="{}"\r\n".format(os.path.basename(file\_path))  
body += b"Content-Type: multipart/form-data;boundary:{}\r\n\r\n".format(boundary)  
body += PyByteArray(file\_data)  
body += b"\r\n--" + boundary + b"--\r\n"

# Set the request method and data

request.get\_method = lambda: 'POST'  
request.add\_data(body)

# Preformatted textSend the request

response = urllib2.urlopen(request)  
print response.getcode()  
print response.info()
