- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
09-23-2020 07:13 AM
Hi All,
I need to download files attached to any incident using REST API.
I will be sending incident detail from my postman.
Already Referred to attachment api reference docs but could'nt find a solution.
NOTE: I don't have the option to use ui action
Is this doable?
Thanks in Advance!
Solved! Go to Solution.
- Labels:
-
Scripting and Coding

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
09-29-2020 02:32 AM
I'm executing python script from the command line.
I may be missing some steps below but the general way to install python is as follows.
1. Install python
https://phoenixnap.com/kb/how-to-install-python-3-windows
2. Create subdirectory
mkdir servicenowapis
3. Move to the subdirectory
cd servicenowapis
4. Create a virtualenv
python-m venv venv
5. Activate venv
venv\Scripts\activate.bat
6. Install request module
pip install requests
7. Copy the script I've provided to the directory
8. Copy and paste content of Constants.py over import statements
9. Edit username, password
9. Edit table_api.py to use Incident number
e.g.
get_file_attachment('INC0000002')
10. Execute command
python test_api.py
import requests
SERVICENOW_URL = 'https://<instance>.service-now.com'
SERVICENOW_USER = '<username>'
SERVICENOW_PWD = '<password>'
DOWNLOAD_DIR = './downloads/'
REQUEST_HEADER = {"json": {"Content-Type": "application/xml", "Accept": "application/json"},
"png": {"Content-Type": "application/xml", "Accept": "application/png"},
"xml": {"Content-Type": "application/xml", "Accept": "application/xml"},
}
ATTACHMENT_API = '/api/now/attachment'
TABLE_API = '/api/now/table'
# TABLE_NAME = 'kb_knowledge'
TABLE_NAME = 'incident'
def get_table_data(table_name, param):
url = SERVICENOW_URL + TABLE_API + '/' + table_name + '?' + param
response = requests.get(url, auth=(SERVICENOW_USER, SERVICENOW_PWD), headers=REQUEST_HEADER.get('json'))
if response.status_code != 200: # if error, then exit
print('Status:', response.status_code, 'Headers:', response.headers, 'Error Response:', response.json())
exit()
return response.json()
def get_attachment_info(sys_id):
url = SERVICENOW_URL + ATTACHMENT_API + '/' + sys_id
response = requests.get(url, auth=(SERVICENOW_USER, SERVICENOW_PWD), headers=REQUEST_HEADER.get('json'))
if response.status_code != 200: # if error, then exit
print(f'Status: {response.status_code}, Headers:{response.headers}')
exit()
return response.json()
def get_attachment(att_sys_id, file_type, download_dir):
url = SERVICENOW_URL + '/' + ATTACHMENT_API + '/' + att_sys_id + '/file'
response = requests.get(url, auth=(SERVICENOW_USER, SERVICENOW_PWD), headers=REQUEST_HEADER.get(file_type))
if response.status_code != 200: # if error, then exit
print('Status:', response.status_code, 'Headers:', response.headers, 'Error Response:', response.json())
exit()
with open(download_dir, 'wb') as f:
for chunk in response:
f.write(chunk)
def get_file_attachment(record_number):
param = 'sysparm_query=number=' + record_number + '&sysparam_limit=1'
file_info = get_table_data(TABLE_NAME, param).get('result')
if len(file_info) < 1:
print(f'There is no attachment to sys_id:{record_number}')
return
attachment_sys_id = file_info[0].get('sys_id')
param = 'sysparm_query=table_sys_id=' + attachment_sys_id + '&sysparam_limit=1'
kb_attachments = get_table_data('sys_attachment', param)
result = kb_attachments.get('result')
for attach_file in result:
attach_sys_id = attach_file.get('sys_id')
content_type = attach_file.get('content_type').split('/')
file_ext = content_type[1]
file_name = attach_file.get('file_name')
get_attachment(attach_sys_id, file_ext, DOWNLOAD_DIR + file_name)
if __name__ == '__main__':
# get_file_attachment('KB0010062') # knowledge base number
get_file_attachment('INC0000002')
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
09-28-2020 12:33 AM
Hi,
So you are trying to send the base64Encoded data to the 3rd party once they consume the endpoint and they will send RITM number.
if yes then please check below
For scoped app use this to get base64data
updated script below
(function process(/*RESTAPIRequest*/ request, /*RESTAPIResponse*/ response) {
// implement resource here
var arr = [];
var queryParams = request.queryParams;
var queryRITM = queryParams.number;
var gr = new GlideRecord('sc_req_item');
gr.addQuery('number', queryRITM);
gr.query();
while (gr.next()) {
var ga = new GlideRecord('sys_attachment');
ga.addQuery('table_sys_id', gr.sys_id);
ga.query();
while (ga.next()) {
var attachsysid = ga.sys_id;
var filename = ga.file_name;
var attachmentRec = new GlideRecord('sys_attachment');
attachmentRec.get(attachsysid);
var sysAtt = new GlideSysAttachment();
var base64Data = sysAtt.getContentBase64(attachmentRec);
var obj = {};
obj["filename"] = filename;
obj["attachmentBase64Data"] = base64Data;
arr.push(obj);
}
}
response.setStatus(200);
response.setBody(obj);
})(request, response);
your sample json output would look like this
{
"result": [
{
"filename": "sample file.txt",
"attachmentBase64Data": "base64DataForThisFile"
},
{
"filename": "sample file.docx",
"attachmentBase64Data": "base64DataForThisFile"
}
]
}
Regards
Ankur
Ankur
✨ Certified Technical Architect || ✨ 9x ServiceNow MVP || ✨ ServiceNow Community Leader
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
09-28-2020 03:29 AM
Hi Ankur,
The json is just returning me the file name.
My requirement is to download the attached file.
I tried below script but when i click send and download from postman, file is downloaded with name 'response' and not in the correct format. I am asked to select the format in which i want to open the downloaded response.
Also, if there are multiple attachments, then only one file is downloaded.
SCRIPT::
var queryParams = request.queryParams;
var queryRITM = queryParams.number;
var gr = new GlideRecord('sc_req_item');
gr.addQuery('number', queryRITM);
gr.query();
while (gr.next()) {
var ga = new GlideRecord('sys_attachment');
ga.addQuery('table_sys_id', gr.sys_id);
ga.query();
while (ga.next()) {
var obj = {};
var attachsysid = ga.sys_id;
var filename = ga.file_name;
obj['Content-Type'] = "'" + ga.content_type + "'";
response.setStatus(200);
response.setHeaders(obj);
var writer = response.getStreamWriter();
var attachmentStream = new GlideSysAttachmentInputStream(attachsysid);
writer.writeStream(attachmentStream);
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
09-28-2020 03:40 AM
Hi,
I believe as per your script it would download only one.
Usually the attachments are transferred in base64Encoded format when integrated with other 3rd party applications.
Regards
Ankur
Ankur
✨ Certified Technical Architect || ✨ 9x ServiceNow MVP || ✨ ServiceNow Community Leader
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
10-05-2020 11:58 PM
Hope you are doing good.
Did you get a chance to check on the comments?
If your query is resolved please mark appropriate response as correct & helpful so that this thread can be closed and others can be benefited by this.
Regards
Ankur
Ankur
✨ Certified Technical Architect || ✨ 9x ServiceNow MVP || ✨ ServiceNow Community Leader

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
09-23-2020 07:47 AM
I haven't done this yet but there's a attachment api with a get method. There's also a curl and python samples. It's going to be necessary to get the sys_ids before calling this API. Will test it out tomorrow during lunch hours. 🙂