Trying to upload files to subfolder in Sharepoint

2020-07-27 06:24发布

问题:

I am new to Powershell and I am trying to upload files from a local folder into Sharepoint online. I seem to get the files into the library, but not into the second subfolder where i want them.

Script so far:

#Specify tenant admin and site URL
$User = "admin@contoso.no"
$SiteURL = "https://contoso.sharepoint.com"
$Folder = "E:\LocalFolder"
$DocLibName = "Libraryname"
$FolderName = "Folder/SubFolder"

#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 = "password"  | ConvertTo-SecureString -AsPlainText -Force

#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()
}

If I use &FolderName = "Folder" the script runs fine. But what do i do to get the files into a subfolder? If I set a filepath as FolderName it does not work. I get the following errors:

You cannot call a method on a null-valued expression.

+ $Upload = $FolderToUpload.Files.Add($FileCreationInfo)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull

Cannot find an overload for "Load" and the argument count: "1".

+ $Context.Load($Upload)
+ ~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodException
    + FullyQualifiedErrorId : MethodCountCouldNotFindBest
    enter code here

Been stuck on this for days :(

回答1:

The error You cannot call a method on a null-valued expression. occurs since the $FolderToUpload object is not getting initialized at line:

$FolderToUpload = $FolderToBindTo | Where {$_.Name -eq $FolderName}

when $FolderName object points to sub folder name

The point is that $List.RootFolder.Folders returns only a folders located one level beneath under list or library, hence sub folder could not be referenced this way.

Instead you could consider the following options to reference a sub folder to add a file.

Using FileCreationInformation.Url property

Use FileCreationInformation.Url property to specify the folder url for a uploaded file.

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


#Upload file(s)
Foreach ($File in (dir $Folder -File))
{
    $FileCreationInfo = New-Object Microsoft.SharePoint.Client.FileCreationInformation
    $FileCreationInfo.Overwrite = $true
    $FileCreationInfo.Content = [System.IO.File]::ReadAllBytes($File.FullName)
    $FileCreationInfo.URL = $List.RootFolder.ServerRelativeUrl + "/" + $FolderName + "/" + $File.Name
    $UploadFile = $List.RootFolder.Files.Add($FileCreationInfo)
    $Context.Load($UploadFile)
    $Context.ExecuteQuery()
}

Using Web.GetFolderByServerRelativeUrl method

Use Web.GetFolderByServerRelativeUrl method to retrieve a folder where file have to be uploaded:

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

$TargetFolder = $Context.Web.GetFolderByServerRelativeUrl($List.RootFolder.ServerRelativeUrl + "/" + $FolderName);


#Upload file(s)
Foreach ($File in (dir $Folder -File))
{
    $FileCreationInfo = New-Object Microsoft.SharePoint.Client.FileCreationInformation
    $FileCreationInfo.Overwrite = $true
    $FileCreationInfo.Content = [System.IO.File]::ReadAllBytes($File.FullName)
    $FileCreationInfo.URL = $File.Name
    $UploadFile = $TargetFolder.Files.Add($FileCreationInfo)
    $Context.Load($UploadFile)
    $Context.ExecuteQuery()
}


回答2:

You can also use the Office 365 Import service to bulk upload files to sharepoint online instead of using CSOM scripts.

This uses the new Sharepoint API which provides much faster speeds without any throttling as it uses scalable azure infrastructure.

https://support.office.com/en-us/article/Use-network-upload-to-import-SharePoint-data-to-Office-365-ed4a43b7-c4e3-45c8-94c8-998153407b8a