Public/Add-JiraIssueAttachment.ps1

function Add-JiraIssueAttachment {
    <#
    .Synopsis
       Adds a file attachment to an existing Jira Issue
    .DESCRIPTION
       This function adds an Attachment to an existing issue in JIRA.
    .EXAMPLE
       Add-JiraIssueAttachment -FilePath "Test comment" -Issue "TEST-001"
       This example adds a simple comment to the issue TEST-001.
    .EXAMPLE
       Get-JiraIssue "TEST-002" | Add-JiraIssueAttachment -FilePath "Test comment from PowerShell"
       This example illustrates pipeline use from Get-JiraIssue to Add-JiraIssueAttachment.
    .INPUTS
       This function can accept JiraPS.Issue objects via pipeline.
    .OUTPUTS
       This function outputs the results of the attachment add.
    .NOTES
       This function requires either the -Credential parameter to be passed or a persistent JIRA session. See New-JiraSession for more details. If neither are supplied, this function will run with anonymous access to JIRA.
    #>

    [CmdletBinding()]
    param(
        # Issue to which to attach the file
        [Parameter(
            Mandatory = $true
        )]
        [ValidateNotNullOrEmpty()]
        [Alias('Key')]
        [Object] $Issue,

        # Path of the file to upload and attach
        [Parameter(
            Mandatory = $true,
            ValueFromPipeline = $true,
            ValueFromPipelineByPropertyName = $true
        )]
        [ValidateScript( { Test-Path $_ })]
        [Alias('InFile', 'FullName')]
        [String[]] $FilePath,

        # Credentials to use to connect to JIRA.
        # If not specified, this function will use anonymous access.
        [Parameter(Mandatory = $false)]
        [PSCredential] $Credential,

        # Whether output should be provided after invoking this function
        [Switch] $PassThru
    )

    Begin {
        Write-Debug "[Add-JiraIssueAttachment] Begin"
        # We can't validate pipeline input here, since pipeline input doesn't exist in the Begin block.
    }

    Process {
        Write-Debug "[$($MyInvocation.MyCommand.Name)] ParameterSetName: $($PsCmdlet.ParameterSetName)"
        Write-Debug "[$($MyInvocation.MyCommand.Name)] PSBoundParameters: $($PSBoundParameters | Out-String)"

        # Validate input object
        if (($Issue.PSObject.TypeNames[0] -ne "JiraPS.Issue") -and (($Issue -isnot [String]))) {
            $message = "Wrong object type provided for Issue. Was $($Issue.GetType().Name)"
            $exception = New-Object -TypeName System.ArgumentException -ArgumentList $message
            Throw $exception
        }

        foreach ($file in $FilePath) {
            # As we are not able to use proper type casting in the parameters, this is a workaround
            # to extract the data from a JiraPS.Issue object
            Write-Debug "[Add-JiraIssueAttachment] Obtaining a reference to Jira issue [$Issue]"
            if ($Issue.PSObject.TypeNames[0] -eq "JiraPS.Issue" -and $Issue.RestURL) {
                $issueObj = $Issue
            }
            elseif ($Issue.PSObject.TypeNames[0] -eq "JiraPS.Issue" -and $Issue.Key) {
                $issueObj = Get-JiraIssue -InputObject $Issue.Key -Credential $Credential -ErrorAction Stop
            }
            else {
                $issueObj = Get-JiraIssue -InputObject $Issue -Credential $Credential -ErrorAction Stop
            }

            $url = "$($issueObj.RestURL)/attachments"

            $fileName = Split-Path -Path $file -Leaf
            $readFile = [System.IO.File]::ReadAllBytes($file)
            $enc = [System.Text.Encoding]::GetEncoding("iso-8859-1")
            $fileEnc = $enc.GetString($readFile)
            $boundary = [System.Guid]::NewGuid().ToString()
            $mimeType = [System.Web.MimeMapping]::GetMimeMapping($file)
            if ($mimeType) { $ContentType = $mimeType }
            else { $ContentType = "application/octet-stream" }

            $bodyLines = @'
--{0}
Content-Disposition: form-data; name="file"; filename="{1}"
Content-Type: {2}
 
{3}
--{0}--
 
'@
 -f $boundary, $fileName, $mimeType, $fileEnc

            $headers = @{
                'X-Atlassian-Token' = 'nocheck'
                'Content-Type'      = "multipart/form-data; boundary=`"$boundary`""
            }
            $parameter = @{
                URI        = $url
                Method     = "POST"
                Body       = $bodyLines
                Headers    = $headers
                RawBody    = $true
                Credential = $Credential
            }
            Write-Debug "[Add-JiraIssueAttachment] Preparing for blastoff!"
            $rawResult = Invoke-JiraMethod @parameter

            if ($PassThru) {
                Write-Debug "[Add-JiraIssueAttachment] -PassThru specified."
                Write-Debug "[Add-JiraIssueAttachment] Converting to custom object"
                ConvertTo-JiraAttachment -InputObject $rawResult

                Write-Debug "[Add-JiraIssueAttachment] Outputting result"
                Write-Output $result
            }
        }
    }

    End {
        Write-Debug "[Add-JiraIssueAttachment] Complete"
    }
}