Public/Add-ServiceNowAttachment.ps1
Function Add-ServiceNowAttachment { <# .SYNOPSIS Attaches a file to an existing record. .DESCRIPTION Attaches a file to an existing record. .PARAMETER Table Name of the table to be queried, by either table name or class name. Use tab completion for list of known tables. You can also provide any table name ad hoc. If using pipeline and this is failing, most likely the table name and class do not match. In this case, provide this value directly. .PARAMETER Id Either the record sys_id or number. If providing just an Id, not with Table, the Id prefix will be looked up to find the table name. .PARAMETER File Path to one or more files to attach .PARAMETER ContentType Content (MIME) type for the file being uploaded. This value will be automatically determined by default, but can be overridden with this parameter. .PARAMETER PassThru Return the newly created attachment details .PARAMETER Connection Azure Automation Connection object containing username, password, and URL for the ServiceNow instance .PARAMETER ServiceNowSession ServiceNow session created by New-ServiceNowSession. Will default to script-level variable $ServiceNowSession. .EXAMPLE Add-ServiceNowAttachment -Id INC0000010 -File @('.\File01.txt', '.\File02.txt') Upload one or more files by record number .EXAMPLE Add-ServiceNowAttachment -Table incident -Id 2306c37c1bafc9100774ebd1b24bcb6d -File @('.\File01.txt', '.\File02.txt') Upload one or more files by record sys_id .EXAMPLE Get-ServiceNowRecord inc0000010 | Add-ServiceNowAttachment -File '.\File01.txt' Use Get-ServiceNowRecord for record details, one or more, to add an attachment to .EXAMPLE New-ServiceNowIncident @params -PassThru | Add-ServiceNowAttachment -File file01.txt Create a new incident and add an attachment .EXAMPLE Add-ServiceNowAttachment -Id INC0000010 -File file01.txt -ContentType 'text/plain' Upload a file and specify the MIME type (content type). Only required if the function cannot automatically determine the type. .EXAMPLE Add-ServiceNowAttachment -Id INC0000010 -File file01.txt -PassThru Upload a file and receive back the file details .INPUTS Table, ID .OUTPUTS System.Management.Automation.PSCustomObject if -PassThru provided #> [OutputType([PSCustomObject[]])] [CmdletBinding(SupportsShouldProcess)] Param( [Parameter(ParameterSetName = 'Table', Mandatory)] [Parameter(ParameterSetName = 'TableId', Mandatory, ValueFromPipelineByPropertyName)] [Alias('sys_class_name')] [string] $Table, # validation not needed as Invoke-TableIdLookup will handle it with -AsSysId [Parameter(ParameterSetName = 'Id', Mandatory, ValueFromPipeline, Position = 0)] [Parameter(ParameterSetName = 'TableId', Mandatory, ValueFromPipelineByPropertyName)] [Alias('sys_id', 'SysId', 'number')] [string] $ID, [Parameter(Mandatory)] [ValidateScript( { if ( Test-Path $_ ) { $true } else { throw 'One or more files do not exist' } })] [string[]] $File, # Content (MIME) type - if not automatically determined [Parameter()] [string] $ContentType, # Allow the results to be shown [Parameter()] [switch] $PassThru, [Parameter()] [Hashtable] $Connection, [Parameter()] [hashtable] $ServiceNowSession = $script:ServiceNowSession ) begin { $auth = Get-ServiceNowAuth -C $Connection -S $ServiceNowSession $params = $auth $params.UseBasicParsing = $true $params.Method = 'POST' } process { $thisTable, $thisID = Invoke-TableIdLookup -T $Table -I $ID -AsSysId -C $Connection -S $ServiceNowSession foreach ($thisFile in $File) { $thisFileObject = Get-ChildItem $thisFile if ( $thisFileObject.Size -eq 0 ) { Write-Warning ('{0} is a 0 byte file and will not be uploaded' -f $thisFileObject.FullName) Continue } If ( -not $PSBoundParameters.ContainsKey('ContentType') ) { # Thanks to https://github.com/samuelneff/MimeTypeMap/blob/master/MimeTypeMap.cs from which # MimeTypeMap.json was adapted $contentTypes = ConvertFrom-Json (Get-Content "$PSScriptRoot\..\config\MimeTypeMap.json" -Raw) $Extension = [IO.Path]::GetExtension($thisFileObject.FullName) $ContentType = $contentTypes.$Extension if ( -not $ContentType ) { Write-Error ('Content type not found for {0}, the file will not be uploaded' -f $thisFileObject.FullName) Continue } } # POST: https://instance.service-now.com/api/now/attachment/file?table_name=incident&table_sys_id=d71f7935c0a8016700802b64c67c11c6&file_name=Issue_screenshot $params.Uri = '{0}/attachment/file?table_name={1}&table_sys_id={2}&file_name={3}' -f $auth.Uri, $thisTable.Name, $thisID, $thisFileObject.Name $params.ContentType = $ContentType $params.InFile = $thisFileObject.FullName If ($PSCmdlet.ShouldProcess(('{0} {1}' -f $thisTable.Name, $ID), ('Add attachment {0}' -f $thisFileObject.FullName))) { Write-Verbose ($params | ConvertTo-Json) $response = Invoke-WebRequest @params if ( $response.Content ) { if ( $PassThru ) { $content = $response.content | ConvertFrom-Json $content.result } } else { # invoke-webrequest didn't throw an error, but we didn't get content back either throw ('"{0} : {1}' -f $response.StatusCode, $response | Out-String ) } } } } } |