The Zurich release has arrived! Interested in new features and functionalities? Click here for more

Download Attachments from TASK/ Incidents - REST API- Python

Nanasaheb
Kilo Contributor

I am using REST API to fetch the Incident and Tasks information but i want to download attachments associated with that tasks and incidents.
Attachment APIs are available but it needs sys_id of that attachment, i am not able to get sys_id for attachments which is attached to that task and incident.

I am using  Python to develop script.

Any one have any idea about it?

 

Thanks in advance.

 

1 ACCEPTED SOLUTION

Hitoshi Ozawa
Giga Sage
Giga Sage

Modified to download attachments to incident. Specify the incident number in get_file_attachment('<incident number>')

import requests

from servicenowapis.constants import ATTACHMENT_API, DOWNLOAD_DIR, REQUEST_HEADER,\
    SERVICENOW_PWD, SERVICENOW_URL,SERVICENOW_USER, TABLE_API, TABLE_NAME


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')

 

Constants.py

SERVICENOW_URL = 'https://<instance>.service-now.com'
SERVICENOW_USER = '<username>'
SERVICENOW_PWD = '<password>'

DOWNLOAD_DIR = 'C:/download/'

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'

View solution in original post

7 REPLIES 7

Hitoshi Ozawa
Giga Sage
Giga Sage

Modified to download attachments to incident. Specify the incident number in get_file_attachment('<incident number>')

import requests

from servicenowapis.constants import ATTACHMENT_API, DOWNLOAD_DIR, REQUEST_HEADER,\
    SERVICENOW_PWD, SERVICENOW_URL,SERVICENOW_USER, TABLE_API, TABLE_NAME


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')

 

Constants.py

SERVICENOW_URL = 'https://<instance>.service-now.com'
SERVICENOW_USER = '<username>'
SERVICENOW_PWD = '<password>'

DOWNLOAD_DIR = 'C:/download/'

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'

Yeah. It works fine. 

Thank You!!

I'm actually building a ServiceNow API Hub by wrapping everything in flask so I can call it from REST url.

Integrating with other services through this hub.

e.g.

from flask import request

from servicenowapis import app
from servicenowapis.table_api import get_file_attachment

@app.route('/')
@app.route('/index')
def index():
    """
    Sample home page used to test connectivity
    :return: Sample string text to show the site is working.
    created: 2020/0709  Hitoshi Ozawa
    """
    message = "<html><body><h1>ServiceNow APIs</h1></body></html>"
    return message


@app.route('/downloadattachments')
def download_attachments():
    ticket_number = request.args.get('number')
    get_file_attachment(ticket_number)
    return "Downloaded attachments to ticket number:" + ticket_number