【问题标题】:Upload large files to sharepoint library subfolder using powershell使用 powershell 将大文件上传到共享点库子文件夹
【发布时间】:2020-04-26 22:49:23
【问题描述】:

我正在使用 PowerShell 将多个 大 文件上传到 SharePoint 库子文件夹。

使用下面的链接/代码,我只能将文件上传到根目录,但不能上传到子文件夹。

如何将其上传到库子文件夹?其他一切正常。

https://www.sharepointsky.com/upload-large-files-to-sharepoint-online-document-library-using-powershell-csom/

【问题讨论】:

  • 废话,在WebApplication中扩展文件支持并通过WebDav下载所有内容更容易,特别是因为你没有SP Online。
  • @Fox 不确定你在说什么。如果您知道如何使用 powershell 进行操作,请回答

标签: powershell sharepoint sharepoint-2013


【解决方案1】:

您正在使用代码将文件添加到文档库的根文件夹:$Docs.RootFolder.Files.Add($FileCreationInfo)

要将文件添加到子文件夹,您需要先获取该子文件夹:

$folder = $web.GetFolderByServerRelativeUrl($folderUrl)
$ctx.Load($folder)
$ctx.ExecuteQuery()

那么你可以像现在一样添加文件

$folder.Files.Add($FileCreationInfo)

【讨论】:

    【解决方案2】:

    供您参考的示例测试脚本。

    $SiteURL = "https://xxxx.sharepoint.com/sites/dev/"
    $libraryName="Testt"
    $SPOnlineUserName="user@xxxx.onmicrosoft.com"
    $SPOnlinePassword="************."
    $fileDirectory="C:\Users\Administrator\Desktop\Downloads"
    $TargetFolderRelativeURL ="/sites/dev/Testt/ccc"
    Try{
    Add-Type -Path 'C:\Program Files\Common Files\microsoft shared\Web Server Extensions\16\ISAPI\Microsoft.SharePoint.Client.dll'
    Add-Type -Path 'C:\Program Files\Common Files\microsoft shared\Web Server Extensions\16\ISAPI\Microsoft.SharePoint.Client.Runtime.dll'
    }
    catch {
    Write-host "No dlls found"
    }
    Function UploadFileInSlice ($ctx, $libraryName, $fileName, $fileChunkSizeInMB) {
    $fileChunkSizeInMB = 9
    # Each sliced upload requires a unique ID.
    $UploadId = [GUID]::NewGuid()
    # Get the name of the file.
    $UniqueFileName = [System.IO.Path]::GetFileName($fileName)
    # Get the folder to upload into.
    $Docs = $ctx.Web.Lists.GetByTitle($libraryName)
    $web=$ctx.Web
    $ctx.Load($Docs)
    $ctx.Load($Docs.RootFolder)
    $ctx.ExecuteQuery()
    # Get the information about the folder that will hold the file.
    $ServerRelativeUrlOfRootFolder = $Docs.RootFolder.ServerRelativeUrl
    # File object.
    [Microsoft.SharePoint.Client.File] $upload
    # Calculate block size in bytes.
    $BlockSize = $fileChunkSizeInMB * 1024 * 1024
    # Get the size of the file.
    $FileSize = (Get-Item $fileName).length
    if ($FileSize -le $BlockSize)
    {
    # Use regular approach.
    $FileStream = New-Object IO.FileStream($fileName,[System.IO.FileMode]::Open, [System.IO.FileAccess]::Read)
    $FileCreationInfo = New-Object Microsoft.SharePoint.Client.FileCreationInformation
    $FileCreationInfo.Overwrite = $true
    $FileCreationInfo.ContentStream = $FileStream
    $FileCreationInfo.URL = $UniqueFileName
    $folder = $web.GetFolderByServerRelativeUrl($TargetFolderRelativeURL)
    $folder.Files.Add($FileCreationInfo)
    $ctx.Load($folder)
    $ctx.ExecuteQuery()
    }
    else
    {
    # Use large file upload approach.
    $BytesUploaded = $null
    $Fs = $null
    Try {
    $Fs = [System.IO.File]::Open($fileName, [System.IO.FileMode]::Open, [System.IO.FileAccess]::Read)
    $br = New-Object System.IO.BinaryReader($Fs)
    $buffer = New-Object System.Byte[]($BlockSize)
    $lastBuffer = $null
    $fileoffset = 0
    $totalBytesRead = 0
    $bytesRead
    $first = $true
    $last = $false
    # Read data from file system in blocks.
    while(($bytesRead = $br.Read($buffer, 0, $buffer.Length)) -gt 0) {
    $totalBytesRead = $totalBytesRead + $bytesRead
    # You've reached the end of the file.
    if($totalBytesRead -eq $FileSize) {
    $last = $true
    # Copy to a new buffer that has the correct size.
    $lastBuffer = New-Object System.Byte[]($bytesRead)
    [array]::Copy($buffer, 0, $lastBuffer, 0, $bytesRead)
    }
    If($first)
    {
    $ContentStream = New-Object System.IO.MemoryStream
    # Add an empty file.
    $fileInfo = New-Object Microsoft.SharePoint.Client.FileCreationInformation
    $fileInfo.ContentStream = $ContentStream
    $fileInfo.Url = $UniqueFileName
    $fileInfo.Overwrite = $true
    $folder = $web.GetFolderByServerRelativeUrl($TargetFolderRelativeURL)
    $folder.Files.Add($fileInfo)
    $ctx.Load($folder)
    $ctx.ExecuteQuery()
    # Start upload by uploading the first slice.
    $s = [System.IO.MemoryStream]::new($buffer)
    # Call the start upload method on the first slice.
    $BytesUploaded = $Upload.StartUpload($UploadId, $s)
    $ctx.ExecuteQuery()
    # fileoffset is the pointer where the next slice will be added.
    $fileoffset = $BytesUploaded.Value
    # You can only start the upload once.
    $first = $false
    }
    Else
    {
    # Get a reference to your file.
    $Upload = $ctx.Web.GetFileByServerRelativeUrl($Docs.RootFolder.ServerRelativeUrl + [System.IO.Path]::AltDirectorySeparatorChar + $UniqueFileName);
    If($last) {
    # Is this the last slice of data?
    $s = [System.IO.MemoryStream]::new($lastBuffer)
    # End sliced upload by calling FinishUpload.
    $Upload = $Upload.FinishUpload($UploadId, $fileoffset, $s)
    $ctx.ExecuteQuery()
    Write-Host "File upload complete"
    # Return the file object for the uploaded file.
    return $Upload
    }
    else {
    $s = [System.IO.MemoryStream]::new($buffer)
    # Continue sliced upload.
    $BytesUploaded = $Upload.ContinueUpload($UploadId, $fileoffset, $s)
    $ctx.ExecuteQuery()
    # Update fileoffset for the next slice.
    $fileoffset = $BytesUploaded.Value
    }
    }
    } #// while ((bytesRead = br.Read(buffer, 0, buffer.Length)) > 0)
    }
    Catch {
    Write-Host "Error occurred"
    }
    Finally {
    if ($Fs -ne $null)
    {
    $Fs.Dispose()
    }
    }
    }
    return $null
    }
    $Context = New-Object Microsoft.SharePoint.Client.ClientContext($SiteURL)
    $securePassword=ConvertTo-SecureString $SPOnlinePassword -AsPlainText -Force
    $Context.Credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($SPOnlineUserName, $securePassword)
    foreach($fileName in Get-ChildItem $fileDirectory)
    {
    $UpFile = UploadFileInSlice -ctx $Context -libraryName $libraryName -fileName $fileName.FullName
    $Context.Dispose();
    }
    

    【讨论】:

    • 谢谢 .... 使用“0”参数调用“ExecuteQuery”的异常:“服务器相关 url 必须以 SPWeb.ServerRelativeUrl 开头”,以及使用“0”调用“ExecuteQuery”的错误异常" 参数:"找不到文件。"...我对 powershell 和 sharepoint 很陌生
    • 文件夹网址应以您的网站网址开头 {/sites/dev/Testt/ccc} 而不是 {/library/folder}。
    • 我正在使用相同的“sites/bu-dam/Operations/Customer%20Care/AccDatabase/Test”,但使用“2”参数调用“StartUpload”时出现错误异常:“对象是未与对象身份关联或对象身份无效。”感谢您的帮助
    【解决方案3】:

    李给你的东西在正确的轨道上,杰克。有几件事你可以做,但你想改变。

    首先 - 由于您使用的是相对 URL,请将其作为参数添加到函数中。这是您的文档库名称之后的 URL 部分(即 /sub-folder/sub-folder):

     Function UploadFileInSlice ($ctx, $libraryName, $fileName, $FolderRelativeURL)
    

    然后 - 创建一个变量来构建您的目标 URL(记得替换空格,并删除逗号:

    $targetURL = "/sites/dev/$($libraryName.Replace(',','').Replace(' ','%20'))$($FolderRelativeURL.Replace(' ','%20'))"
    

    下一步 - 由于您使用的是相对 URL,因此无需加载根文件夹。您仍然可以使用其相对 URL 上传到它。但是,您将希望您的上下文在以后知道目标文件夹。所以在函数开始之前,你只需要这 4 行来设置你的上下文:

    $web = $ctx.web
    $folder = $web.GetFolderByServerRelativeUrl($targetURL)
    $ctx.Load($folder)
    $ctx.ExecuteQuery()
    

    Lee 在“常规方法”中提供的位适用于小于块大小的文件,但在大文件部分,您希望使用该 $upload 对象。您需要该对象才能让其余代码上传切片。与您的原始来源和 Lee 的回答相比,这应该看起来很熟悉:

    $Upload = $folder.Files.Add($fileInfo)
    

    最后 - 在第一个切片(空文件)上传后,您需要更改 $upload 对象的引用。原始代码仍在查看文件的根目录。您必须将其定向到您的相对 URL。由于您之前已将文件夹加载到上下文中,因此您可以检索所需的属性(在本例中,您将获得其 ServerRelativeUrl):

    $Upload = $ctx.Web.GetFileByServerRelativeUrl($folder.ServerRelativeUrl + [System.IO.Path]::AltDirectorySeparatorChar + $UniqueFileName);
    

    我有构建 2 个不同 URL 的脚本的原因是因为 $web.GetFolderByServerRelativeUrl 想要一个 Web URL(这意味着 %20 而不是空格并且没有逗号),而 $ctx.Web.GetFileByServerRelativeUrl 想要一个直接 URL(它可以有空格;它不喜欢带有 %20 的 URL)。您可能没有这个问题,并且可以跳过其中的一些代码。然而,我的用户对我并不友善,并且尽可能使用空格。

    最后一点,您可能希望在“常规方法”部分的“返回”之前添加 $Filestream.dispose()。没有它,该文件将被锁定,直到脚本结束,如果需要,您以后无法访问/修改它。

    我希望这对您有所帮助。我也不得不在互联网上搜索如何将大文件上传到子目录中。

    【讨论】:

    • 我猜这个附加参数不是必需的,但它使函数在脚本 imo 中更有用。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-09-26
    • 2019-11-14
    • 2012-12-25
    • 2011-01-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多