当前位置:网站首页 > 更多 > 玩电脑 > 正文

[玩转系统] SharePoint Online:使用 PowerShell 上传大文件

作者:精品下载站 日期:2024-12-14 15:50:23 浏览:13 分类:玩电脑

SharePoint Online:使用 PowerShell 上传大文件


要求:使用 PowerShell 将大文件上传到 SharePoint Online。

PowerShell 将大文件上传到 SharePoint Online

假设您尝试使用 CSOM Files.Add 方法或 PnP PowerShell Add-PnPFile 方法将文件大小 > 250 MB 的文件上传到 SharePoint Online,您最终会遇到错误:

  • “远程服务器返回错误:(503) 服务器不可用。”
  • “Add-PnPFile:请求消息太大。服务器不允许消息大于 262144000 字节”
  • Add-PnPFile:基础连接已关闭:发送时发生意外错误
  • Add-PnPFile :远程服务器返回错误:(404) 未找到

缓解错误的方法 以下是如何使用 PowerShell 将较大的文件上传到 SharePoint Online:


#Load SharePoint CSOM Assemblies
Add-Type -Path "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\ISAPI\Microsoft.SharePoint.Client.dll"
Add-Type -Path "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\ISAPI\Microsoft.SharePoint.Client.Runtime.dll"

#Parameters
$SiteURL = "https://crescent.sharepoint.com/sites/marketing" 
$TargetFolderURL = "/sites/marketing/Shared Documents"
$FilePath =  "C:\Users\Thomas\Downloads\WFx64.zip"
 
#Get Credentials to connect
$Cred = Get-Credential

Try { 
    #Setup the context
    $Ctx = New-Object Microsoft.SharePoint.Client.ClientContext($SiteURL)
    $Ctx.Credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($Cred.UserName,$Cred.Password)

    #Get the file from disk
    $FileStream = ([System.IO.FileInfo] (Get-Item $FilePath)).OpenRead()

    #Calculate Target URL
    $SourceFileName = Split-path $FilePath -leaf
    $TargetFileURL = $TargetFolderURL+"/"+$SourceFileName

    #Upload Large File to SharePoint Online
    $Ctx.RequestTimeout = [System.Threading.Timeout]::Infinite
    [Microsoft.SharePoint.Client.File]::SaveBinaryDirect($Ctx, $TargetFileURL, $FileStream,$True)
             
    Write-host "File uploaded Successfully!" -f Green
}
Catch {
    write-host "Error Uploading File: $($_.Exception.Message)" -foregroundcolor Red
}

但是,当您从慢速网络上传较大文件时,如果上传操作时间超过 30 分钟,则会超时。

SharePoint Online 文件大小限制
  • 250 GB - 文件上传限制。适用于每个单独的文件
  • 250 MB - 附加到列表项的文件。

PowerShell 将大文件分块上传到 SharePoint Online:

我们可以将其拆分为较小的块并上传,而不是一次性上传较大的文件。


#Function to Upload Large File to SharePoint Online Library
Function Upload-LargeFile($FilePath, $LibraryName, $FileChunkSize=10)
{
    Try {
        #Get File Name
        $FileName = [System.IO.Path]::GetFileName($FilePath)
        $UploadId = [GUID]::NewGuid()

        #Get the folder to upload
        $Library = $Ctx.Web.Lists.GetByTitle($LibraryName)
        $Ctx.Load($Library)
        $Ctx.Load($Library.RootFolder)
        $Ctx.ExecuteQuery()

        $BlockSize = $FileChunkSize * 1024 * 1024  
        $FileSize = (Get-Item $FilePath).length
        If($FileSize -le $BlockSize)
        {
            #Regular upload
            $FileStream = New-Object IO.FileStream($FilePath,[System.IO.FileMode]::Open)
            $FileCreationInfo = New-Object Microsoft.SharePoint.Client.FileCreationInformation
            $FileCreationInfo.Overwrite = $true
            $FileCreationInfo.ContentStream = $FileStream
            $FileCreationInfo.URL = $FileName
            $Upload = $Docs.RootFolder.Files.Add($FileCreationInfo)
            $ctx.Load($Upload)
            $ctx.ExecuteQuery()
        }
        Else
        {
            #Large File Upload in Chunks
            $ServerRelativeUrlOfRootFolder = $Library.RootFolder.ServerRelativeUrl
            [Microsoft.SharePoint.Client.File]$Upload
            $BytesUploaded = $null  
            $Filestream = $null
            $Filestream = [System.IO.File]::Open($FilePath, [System.IO.FileMode]::Open, [System.IO.FileAccess]::Read, [System.IO.FileShare]::ReadWrite)
            $BinaryReader = New-Object System.IO.BinaryReader($Filestream)
            $Buffer = New-Object System.Byte[]($BlockSize)
            $LastBuffer = $null
            $Fileoffset = 0
            $TotalBytesRead = 0
            $BytesRead
            $First = $True
            $Last = $False

            #Read data from the file in blocks
            While(($BytesRead = $BinaryReader.Read($Buffer, 0, $Buffer.Length)) -gt 0)
            {  
                $TotalBytesRead = $TotalBytesRead + $BytesRead  
                If ($TotalBytesRead -eq $FileSize) 
                {  
                    $Last = $True
                    $LastBuffer = New-Object System.Byte[]($BytesRead)
                    [Array]::Copy($Buffer, 0, $LastBuffer, 0, $BytesRead)  
                }
                If($First) 
                {  
                    #Create the File in Target
                    $ContentStream = New-Object System.IO.MemoryStream
                    $FileCreationInfo = New-Object Microsoft.SharePoint.Client.FileCreationInformation
                    $FileCreationInfo.ContentStream = $ContentStream
                    $FileCreationInfo.Url = $FileName
                    $FileCreationInfo.Overwrite = $true
                    $Upload = $Library.RootFolder.Files.Add($FileCreationInfo)
                    $Ctx.Load($Upload)

                    #Start FIle upload by uploading the first slice
                    $s = new-object System.IO.MemoryStream(, $Buffer)  
                    $BytesUploaded = $Upload.StartUpload($UploadId, $s)
                    $Ctx.ExecuteQuery()  
                    $fileoffset = $BytesUploaded.Value  
                    $First = $False  
                }  
                Else
                {  
                    #Get the File Reference
                    $Upload = $ctx.Web.GetFileByServerRelativeUrl($Library.RootFolder.ServerRelativeUrl + [System.IO.Path]::AltDirectorySeparatorChar + $FileName);
                    If($Last) 
                    {
                        $s = [System.IO.MemoryStream]::new($LastBuffer)
                        $Upload = $Upload.FinishUpload($UploadId, $fileoffset, $s)
                        $Ctx.ExecuteQuery()
                        Write-Host "File Upload completed!" -f Green                        
                    }
                    Else
                    {
                        #Update fileoffset for the next slice
                        $s = [System.IO.MemoryStream]::new($buffer)
                        $BytesUploaded = $Upload.ContinueUpload($UploadId, $fileoffset, $s)
                        $Ctx.ExecuteQuery()
                        $fileoffset = $BytesUploaded.Value
                    }
                }
            }
        }
    }
    Catch {
        Write-Host $_.Exception.Message -ForegroundColor Red
    }
    Finally {
        If($Filestream -ne $null)
        {
            $Filestream.Dispose()
        }
    }
}

#Connect to SharePoint Online site
Connect-PnPOnline "https://crescent.sharepoint.com/sites/marketing" -Interactive
$Ctx = Get-PnPContext

#Call the function to Upload File
Upload-LargeFile -FilePath "C:\Users\Thomas\Downloads5021WFx64.rar" -LibraryName "Documents"

顺便说一句,我已将该方法转换为 PowerShell,如 https://docs.microsoft.com/en-us/sharepoint/dev/solution-guidance/upload-large-files-sample-app-for-sharepoint 中所述

您需要 登录账户 后才能发表评论

取消回复欢迎 发表评论:

关灯