Office 365 – PowerShell Script to Upload Files to a Document Library using CSOM


UPDATE: My colleague Roger Cormier has created a far superior version of this script that is able to handle sub-folders, please check it out – https://gallery.technet.microsoft.com/PowerShell-Bulk-Upload-b9e9d600

Another PowerShell sample script for you. This one uploads all files within a specified local directory to a Document Library within a Site in an O365 tenant.

All you need to run this script is an O365 tenant, the SharePoint client components SDK installed on the machine running the script – http://www.microsoft.com/en-us/download/details.aspx?id=35585 and to update the $User, $SiteURL, $DocLibName (name of the destination Document library) and $Folder (path to the local folder containing the files to upload) variables. When the script is executed it will prompt for the password of the user specific in the $User variable.

#Specify tenant admin and site URL
$User = "admin@tenant.onmicrosoft.com"
$SiteURL = "https://tenant.sharepoint.com/sites/site"
$Folder = "C:\FilesToUpload"
$DocLibName = "DocLib"

#Add references to SharePoint client assemblies and authenticate to Office 365 site – required for CSOM
Add-Type -Path "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\15\ISAPI\Microsoft.SharePoint.Client.dll"
Add-Type -Path "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\15\ISAPI\Microsoft.SharePoint.Client.Runtime.dll"
$Password = Read-Host -Prompt "Please enter your password" -AsSecureString

#Bind to site collection
$Context = New-Object Microsoft.SharePoint.Client.ClientContext($SiteURL)
$Creds = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($User,$Password)
$Context.Credentials = $Creds

#Retrieve list
$List = $Context.Web.Lists.GetByTitle($DocLibName)
$Context.Load($List)
$Context.ExecuteQuery()

#Upload file
Foreach ($File in (dir $Folder -File))
{
$FileStream = New-Object IO.FileStream($File.FullName,[System.IO.FileMode]::Open)
$FileCreationInfo = New-Object Microsoft.SharePoint.Client.FileCreationInformation
$FileCreationInfo.Overwrite = $true
$FileCreationInfo.ContentStream = $FileStream
$FileCreationInfo.URL = $File
$Upload = $List.RootFolder.Files.Add($FileCreationInfo)
$Context.Load($Upload)
$Context.ExecuteQuery()
}


Brendan Griffin

Comments (32)

  1. Looks as though it is having an issue connecting to the list specified in the $DocLibName variable, may be worth checking this to ensure that the library is present.

  2. Yes, I’m actually working on something very similar at the moment. Will post once it’s ready.

  3. I have updated the script to support files larger than 2MB.

  4. There is an article here – http://www.c-sharpcorner.com/Blogs/12139/how-to-create-document-set-using-csom-in-sharepoint-2013.aspx but it’s using C#, should be easy enough to convert to PS. I may even do a Blog post on it 🙂

  5. Office 365 – PowerShell Script to Upload Files to a Document Library using CSOM
    hassan sayed issa

  6. Keith Tuomi says:

    Thanks Brendan – do you know of a similar routine that would let one create a new Document set and upload documents into it?

  7. Keith Tuomi says:

    Great, thanks. One more question- in regards to the 2MB limit- the Answer on the post at http://social.msdn.microsoft.com/Forums/sharepoint/en-US/deac7cb7-c677-47b0-acdc-c56b32dfaac8/uploading-bigger-files-using-csom?forum=sharepointdevelopment seems to demonstrate the streaming method necessary to overcome the 2MB limit. Do you know if that’s possible to recreate the streaming method in PowerShell as opposed to the C# example provided?

  8. Tenille Bennett says:

    Hi, brilliant work, do you know if its possible to create a script to download/ copy all documents from an O365 site collection to a local drive?

    Thanks

  9. RODNEY says:

    Love the script.
    Wondering how to tweak it to upload meta data with the files also?
    Thanks.

  10. Prasanna Sridharan says:

    Hi, is it possible to share the similar script for download?

  11. Venkatesh says:

    I am not sure why I am only getting the below error while executing this code. Please help me to fix.

    You cannot call a method on a null-valued expression.
    At D:SP2013 OnlineOnlineWorksget site informationtest.ps1:24 char:1
    + $List = $Context.Web.Lists.GetByTitle($DocLibName)
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull

    You cannot call a method on a null-valued expression.
    At D:SP2013 OnlineOnlineWorksget site informationtest.ps1:25 char:1
    + $Context.Load($List)
    + ~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull

    You cannot call a method on a null-valued expression.
    At D:SP2013 OnlineOnlineWorksget site informationtest.ps1:26 char:1
    + $Context.ExecuteQuery()
    + ~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull

    2
    True
    3
    True
    2
    Success
    Close
    You cannot call a method on a null-valued expression.
    At D:SP2013 OnlineOnlineWorksget site informationtest.ps1:63 char:1
    + $Upload = $List.RootFolder.Files.Add($FileCreationInfo)
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull

    You cannot call a method on a null-valued expression.
    At D:SP2013 OnlineOnlineWorksget site informationtest.ps1:64 char:1
    + $Context.Load($Upload)
    + ~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull

    You cannot call a method on a null-valued expression.
    At D:SP2013 OnlineOnlineWorksget site informationtest.ps1:65 char:1
    + $Context.ExecuteQuery()
    + ~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull

  12. Doron says:

    Trying to move a file inside sharepoint from folder A to folder ADone (After processing). Do you have any sample script i can use to move a file?

    Thanks

  13. Rocco says:

    I am unable to get this script to work- i get an error in powershell. I made a copy of the directory that I need to upload and gave “full access” NTFS permission to “everyone” just for the sake of testing and ruling out NTFS Perms… any suggestions?

    New-Object : Exception calling “.ctor” with “2” argument(s): “Access to the path ‘E:filesSALES_DOCUMENTS’ is denied.”
    At line:25 char:15
    + $FileStream = New-Object IO.FileStream($File.FullName,[System.IO.FileMode]::Open …
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : InvalidOperation: (:) [New-Object], MethodInvocationException
    + FullyQualifiedErrorId : ConstructorInvokedThrowException,Microsoft.PowerShell.Commands.NewObjectCommand

    Exception calling “Add” with “1” argument(s): “Cannot access a closed file.”
    At line:30 char:1
    + $Upload = $List.RootFolder.Files.Add($FileCreationInfo)
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : ObjectDisposedException

    Exception calling “Load” with “1” argument(s): “The object is used in the context different from the one associated with the object.”
    At line:31 char:1
    + $Context.Load($Upload)
    + ~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : InvalidOperationException

    Exception calling “ExecuteQuery” with “0” argument(s): “Invalid request.”
    At line:32 char:1
    + $Context.ExecuteQuery()
    + ~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : ServerException

  14. SharePoint Specialist says:

    Hi, Can you please provide the script to upload more than 2MB file size, I am looking up to 2GB file size upload. Please send script to sharepointind@gmail.com

    Thanks for your help.

  15. DearbhlaB says:

    Hi,
    I was wondering if you are able to create folders in the same way?

  16. Ove Bristrand says:

    I hope you would add some lines to the script to keep the changed date and the author of the files.

  17. Dionro says:

    Is there a way to have the file checked in? As when it gets uploaded it is left checked out…would like to automate the check in process as well.

    Thanks.

  18. shelle0175 says:

    Is it possible to have the results of what is going on in the script be displayed on the screen for when I have users run the script?

  19. vivek pandey says:

    I am also looking for Powershell Script for Creating Document Sets in Bulk.
    Please give some idea or any body can send some script for this.
    I am using SharePoint online 2013(Office 365)

  20. PNWR968 says:

    Your script works quite well, but I’m having a devil of a time figuring out how to upload to an established subdirectory/subfolder in the library. Any advice would be helpful. Thanks!

  21. vzion says:

    How about script to upload a list template file in all user’s mySite?
    Thanks.

  22. Dave says:

    Is there a way of retaining the office documents properties

  23. Deepak says:

    Hi brandon i need powershell script to download files from o365 on specified local directory.
    plz need that script , thanks in advance

  24. I managed to get this Script working on SharePoint 2013 site, I would like to upload the file(s) into a subfolder in the site Library, but have not been able to achieve this, how can this be done?
    ________________________
    #Specify tenant admin and site URL
    $user = "Username@domain.com"
    $SiteURL = "http://mysite2013.test.domain.com/personal/spruit1/Shared_Library/"
    $Folder = "C:TempTemp1"
    $DocLibName = "Shared_Library"

    #Add references to SharePoint client assemblies and authenticate to Office 365 site – required for CSOM
    Add-Type -Path "C:Program FilesCommon FilesMicrosoft SharedWeb Server Extensions15ISAPIMicrosoft.SharePoint.Client.dll"
    Add-Type -Path "C:Program FilesCommon FilesMicrosoft SharedWeb Server Extensions15ISAPIMicrosoft.SharePoint.Client.Runtime.dll"
    $Password = Read-Host -Prompt "Please enter your password" -AsSecureString

    #Bind to site collection
    $Context = New-Object Microsoft.SharePoint.Client.ClientContext($SiteURL)
    $Creds = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($user,$Password)
    $Context.Credentials = $Creds
    # !!Had s removed from above $creds!!

    #Retrieve list
    # $List = $Context.Web.Lists.GetByTitle($DocLibName)
    $List = $Context.Web.Lists.GetByTitle("Certificates")
    $Context.Load($List)
    $Context.ExecuteQuery()

    #Upload file
    Foreach ($File in (dir $Folder -File))
    {
    $FileStream = New-Object IO.FileStream($File.FullName,[System.IO.FileMode]::Open)
    $FileCreationInfo = New-Object Microsoft.SharePoint.Client.FileCreationInformation
    $FileCreationInfo.Overwrite = $true
    $FileCreationInfo.ContentStream = $FileStream
    $FileCreationInfo.URL = $File
    $Upload = $List.RootFolder.Files.Add($FileCreationInfo)
    $Context.Load($Upload)
    $Context.ExecuteQuery()
    }
    # source:
    http://blogs.technet.com/b/fromthefield/archive/2014/02/19/office365-script-to-upload-files-to-a-document-library-using-csom.aspx
    ___________________________________________________
    I tried to use $DocLibName = "Shared_Library/SubFolder" and created this folder first.

    I also managing SharePoint 2010 sites and like to achieve the same, however above script which work for SharePoint 2013 sites fails for SharePoint 2010 sites.

    How can I achieve this?
    Regards Petro.

  25. @Petro – here is an updated version that can target a specific folder:

    $FolderName is the name of the folder within the doc lib to upload files to.

    $Folder = "D:FilesToUpload"
    $DocLibName = "Documents"
    $FolderName = "Folder"

    #Add references to SharePoint client assemblies and authenticate to Office 365 site – required for CSOM
    Add-Type -Path "C:Program FilesCommon FilesMicrosoft SharedWeb Server Extensions16ISAPIMicrosoft.SharePoint.Client.dll"
    Add-Type -Path "C:Program FilesCommon FilesMicrosoft SharedWeb Server Extensions16ISAPIMicrosoft.SharePoint.Client.Runtime.dll"
    $Password = Read-Host -Prompt "Please enter your password" -AsSecureString

    #Bind to site collection
    $Context = New-Object Microsoft.SharePoint.Client.ClientContext($SiteURL)
    $Creds = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($User,$Password)
    $Context.Credentials = $Creds

    #Retrieve list
    $List = $Context.Web.Lists.GetByTitle($DocLibName)
    $Context.Load($List)
    $Context.ExecuteQuery()

    #Retrieve folder
    $FolderToBindTo = $List.RootFolder.Folders
    $Context.Load($FolderToBindTo)
    $Context.ExecuteQuery()
    $FolderToUpload = $FolderToBindTo | Where {$_.Name -eq $FolderName}

    #Upload file
    Foreach ($File in (dir $Folder -File))
    {
    $FileStream = New-Object IO.FileStream($File.FullName,[System.IO.FileMode]::Open)
    $FileCreationInfo = New-Object Microsoft.SharePoint.Client.FileCreationInformation
    $FileCreationInfo.Overwrite = $true
    $FileCreationInfo.ContentStream = $FileStream
    $FileCreationInfo.URL = $File
    $Upload = $FolderToUpload.Files.Add($FileCreationInfo)
    $Context.Load($Upload)
    $Context.ExecuteQuery()
    }

  26. peterritz says:

    Thanks for sharing this informative article.
    Though, in my case to fulfill our requirement without technical expertise, we used a tool named LepideMigrator for Documents (http://www.lepide.com/lepidemigratordocuments/ ) that worked perfectly
    to get this job done.
    However, I have bookmarked this article to get help in coming future and hope, it would be a nice destination for us.

  27. Brendan Griffin, thanks for your answer. It work great for SharePoint 2013.

    I need to get it also working fro SharePoint 2010, but it fails on line 46 $Context.Load($Upload)

    I updated the script with reference to SharePoint 2010 Microsoft SharePoint Client DLL’s.
    Add-Type -Path "C:Program FilesCommon FilesMicrosoft SharedSharePoint ClientMicrosoft.SharePoint.Client.dll"
    Add-Type -Path "C:Program FilesCommon FilesMicrosoft SharedSharePoint ClientMicrosoft.SharePoint.Client.Runtime.dll"

    The error I got is:
    Exception calling "ExecuteQuery" with "0" argument(s): "Data at the root level is invalid. Line 2, position 1."
    At G:PowershellClient Metadata defaultsClient_LocationBasedDefaultWorking on uploading File PowershellScript.ps1:46 char:5
    + $Context.ExecuteQuery()
    + ~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : ServerException

    Can you explain what need to be changed more to get this script working fro SharePoint 2010 sites?
    Thank

    1. Jairo says:

      I have the same Issue…
      Exception calling “ExecuteQuery” with “0” argument(s): “Data at the root level is invalid. Line 2, position 1.”
      Anyone with some comment about this error???
      Thanks

      1. Ricardo says:

        I’m having the same issue in Sp2010, did you solve it?
        Help wuold be very much appreciated.

        Thanks

  28. Matt says:

    Excellent, very easy to use. Please could you also explain how I can also add field/column data to the file that’s uploaded. Once the file is online, I could use $item["Project Name "] = "Test Project" but can this be done within the upload script?

  29. Matt says:

    $item = $Upload.ListItemAllFields
    $item["Customer Field"] = "Field Text"
    $item.Update()

  30. Mark Orser says:

    The Folder script in the comments worked to get the files into a folder off root.

    How can I upload the file into a folder 2 deep? A subfolder of a folder off root?
    Thanks.