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. Anonymous says:

    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. Anonymous says:

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

  3. Anonymous says:

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

  4. Anonymous says:

    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. Anonymous says:

    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.