4

I'm attempting to upload a file to SharePoint 2010:

Function Add-Attachments()
{

    [CmdletBinding()]
    Param(
        [Parameter(Mandatory=$True)]
        [int]$Id,
        [Parameter(Mandatory=$True)]
        [string[]]$Paths
    )

    BEGIN {}
    PROCESS {

        $url = "http://server/resource/_vti_bin/listdata.svc/TheList($Id)/Attachments"

        Foreach ($Path in $Paths) {

            Write-Verbose "Attaching $Path ..."
            $headers = @{
                'Slug' = "TheList|$Id|$(Split-Path $path -Leaf)"
            }

            $Payload = @{filename=(Split-Path $path -Leaf);filecontent=([IO.File]::ReadAllBytes($path))}

            Invoke-WebRequest -Uri $url -Method Post -UseDefaultCredentials -Body $Payload -Headers $headers

        } # Foreach

    } # PROCESS
    END {}

}

Add-Attachments -Id 1234 -Paths 'C:\Users\gandalf\Desktop\test.txt' -verbose

I get an error that reads:

Invoke-WebRequest : An error occurred while processing this request. At C:\Users\gandalf\Documents\WindowsPowerShell\Scripts\SP\SharePoint2010.ps1:382 char:13 + Invoke-WebRequest -Uri $url -Method Post -UseDefaultCredentials -Bod ... + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-WebRequest], WebException + FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand

** edit **

The file's original content:

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Donec et mollis dolor. Praesent et diam eget libero egestas mattis sit amet vitae augue. Nam tincidunt congue enim, ut porta lorem lacinia consectetur. Donec ut libero sed arcu vehicula ultricies a non tortor. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean ut gravida lorem. Ut turpis felis, pulvinar a semper sed, adipiscing id dolor. Pellentesque auctor nisi id magna consequat sagittis. Curabitur dapibus enim sit amet elit pharetra tincidunt feugiat nisl imperdiet. Ut convallis libero in urna ultrices accumsan. Donec sed odio eros. Donec viverra mi quis quam pulvinar at malesuada arcu rhoncus. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. In rutrum accumsan ultricies. Mauris vitae nisi at sem facilisis semper ac in est.

The script does create a file on the server, but with this content:

filename=test.txt&filecontent=Lorem+ipsum+dolor+sit+amet%2c+consectetur+adipiscing+elit.+Donec+a+diam+lectus.+Sed+sit+amet+ipsum+mauris.+Maecenas+congue+ligula+ac+quam+viverra+nec+consectetur+ante+hendrerit.+Donec+et+mollis+dolor.+Praesent+et+diam+eget+libero+egestas+mattis+sit+amet+vitae+augue.+Nam+tincidunt+congue+enim%2c+ut+porta+lorem+lacinia+consectetur.+Donec+ut+libero+sed+arcu+vehicula+ultricies+a+non+tortor.+Lorem+ipsum+dolor+sit+amet%2c+consectetur+adipiscing+elit.+Aenean+ut+gravida+lorem.+Ut+turpis+felis%2c+pulvinar+a+semper+sed%2c+adipiscing+id+dolor.+Pellentesque+auctor+nisi+id+magna+consequat+sagittis.+Curabitur+dapibus+enim+sit+amet+elit+pharetra+tincidunt+feugiat+nisl+imperdiet.+Ut+convallis+libero+in+urna+ultrices+accumsan.+Donec+sed+odio+eros.+Donec+viverra+mi+quis+quam+pulvinar+at+malesuada+arcu+rhoncus.+Cum+sociis+natoque+penatibus+et+magnis+dis+parturient+montes%2c+nascetur+ridiculus+mus.+In+rutrum+accumsan+ultricies.+Mauris+vitae+nisi+at+sem+facilisis+semper+ac+in+est.

What am I missing? Do I need to include the content length? Set the MIME type?

craig
  • 25,664
  • 27
  • 119
  • 205
  • 1
    Have you tried with Fiddler to see traffic from server ? If on premise check ULS log – Max Jun 17 '15 at 09:09
  • A few questions: 1) Are you trying to attach a file to an existing list item or are you wanting to just upload the file to a folder? /Attachments should be specific to attaching to list items. 2) Is this being uploaded from a server in the farm or is this remote? 3) What line in the code does 382 point to? (as you only have 35 lines, I assume there's more). – Graham Jun 19 '15 at 17:55
  • 1. attach file to existing list item 2. uploaded from workstation 3. needs research – craig Jun 19 '15 at 21:01

1 Answers1

2

In order to create an attachment resource the following properties have to be specified:

Endpoint Uri: http://server/site/_vti_bin/listdata.svc/entityset(itemid)/Attachments
Method: POST
Headers:
   Slug: "entityset|itemid|name"
   ContentType: */* 
Body: content

Having said that, my conslution that the specified body parameter ($payload) is invalid in the provided example.

The following example demonstrates how to upload attachment file via SharePoint 2010 REST Interface:

Function Add-Attachments()
{

    [CmdletBinding()]
    Param(
        [Parameter(Mandatory=$True)]
        [string]$WebUrl, 
        [Parameter(Mandatory=$True)]
        [string]$ListName, 
        [Parameter(Mandatory=$True)]
        [int]$ItemId,
        [Parameter(Mandatory=$True)]
        [string]$SourcePath
    )

    BEGIN {}
    PROCESS {
        $endpointUri = New-Object System.Uri("$WebUrl/_vti_bin/listdata.svc/$ListName($ItemId)/Attachments")
        $fileName = (Split-Path $SourcePath -Leaf)
        $fileContent = ([IO.File]::ReadAllBytes($SourcePath))
        $headers = @{
                 'Slug' = "$ListName|$ItemId|$fileName";
        }

        Invoke-WebRequest -Uri $endpointUri -Method Post -UseDefaultCredentials -Body $fileContent -Headers $headers -ContentType "*/*"

    } # PROCESS
    END {}

}

Usage:

Add-Attachments -WebUrl "http://contoso.intranet.com/" -ListName "Tasks" -ItemId 1 -SourcePath "C:\Users\user\Documents\SharePointUserGuide.docx" -verbose

Update

After performing some analysis via Fiddler, it was determined that the proper endpoint url should be:

/_vti_bin/listdata.svc/Attachments HTTP/1.1

instead of:

/_vti_bin/listdata.svc/Tasks(<id>)/Attachments HTTP/1.1

Modified example

Function Add-Attachments()
{

    [CmdletBinding()]
    Param(
        [Parameter(Mandatory=$True)]
        [string]$WebUrl, 
        [Parameter(Mandatory=$True)]
        [string]$ListName, 
        [Parameter(Mandatory=$True)]
        [int]$ItemId,
        [Parameter(Mandatory=$True)]
        [string]$SourcePath
    )

    BEGIN {}
    PROCESS {
        $endpointUri = New-Object System.Uri("$WebUrl/_vti_bin/listdata.svc/Attachments")  
        $fileName = (Split-Path $SourcePath -Leaf)
        $fileContent = ([IO.File]::ReadAllBytes($SourcePath))
        $headers = @{
                 'Slug' = "$ListName|$ItemId|$fileName";
        }

        Invoke-WebRequest -Uri $endpointUri -Method Post -UseDefaultCredentials -Body $fileContent -Headers $headers -ContentType "*/*"

    } # PROCESS
    END {}

}
Vadim Gremyachev
  • 57,952
  • 20
  • 129
  • 193
  • Would this work to *replace* a file (assuming same names) with a new version? Or would the method need to be `PUT`? – craig Jun 20 '15 at 00:30
  • The function returns `System.Net.WebException: The remote server returned an error: (500) Internal Server Error.`. On a positive note, the file is attached to the task and its content appears to be valid. Thoughts? – craig Jun 20 '15 at 21:56
  • 1
    [Relevant?](https://stackoverflow.com/questions/22696981/get-http-request-and-tolerate-500-server-error-in-powershell) – craig Jun 21 '15 at 21:00
  • It seems so, tried to consume the same request via c# Web Request but never encountered the same error.. – Vadim Gremyachev Jun 21 '15 at 21:36
  • Or [this](https://sharepoint.stackexchange.com/questions/43543/how-to-debug-500-internal-server-error-when-calling-web-services)? – craig Jun 22 '15 at 02:38
  • Looks like the issue was related with endpoint url, just updated the answer – Vadim Gremyachev Jun 22 '15 at 07:37
  • how to use this with javascript please help me – Kem Bardly Apr 15 '17 at 07:13