Saltar al contenido

Sharepoint: carga de un archivo grande en Office 365 a través de CSOM PowerShell

Si te encuentras con alguna parte que no entiendes puedes comentarlo y trataremos de ayudarte rápidamente.

Solución:

Si está siguiendo Office Dev PnP, entonces han lanzado enfoques brillantes para cargar archivos de varios tamaños. Su código está en c #, que convertimos a PowerShell.

Tuve exactamente el mismo escenario en el que necesitaba cargar archivos de tamaño superior a 500 MB o 1 GB y luego actualizar las propiedades de metadatos. Usé PowerShell csom para esto.

Office Dev PnP ha mencionado 4 tipos de métodos, te informaré sobre 2. Y te pediré que leas en detalle sobre la carga de archivos grandes con CSOM en GitHub y la aplicación de muestra de carga de archivos grandes para SharePoint en MSDN.

  1. SaveBinaryDirect: No hay limitaciones de tamaño de archivo, pero hay un tiempo de espera de seguridad después de 30 minutos. Utilice este método solo si está utilizando una política de autenticación solo para usuarios. La política de autenticación solo para usuarios no está disponible en una aplicación para SharePoint, pero se puede usar en aplicaciones de dispositivos nativos, Windows PowerShell y aplicaciones de consola de Windows.

    $Context.RequestTimeout = [System.Threading.Timeout]::Infinite
    [Microsoft.SharePoint.Client.File]::SaveBinaryDirect($Context, $fileUrl, $LocalFile.OpenRead(), $true)
    

    Nota: Inicialmente estaba usando este método sin configurar Request Timeout en infinito, lo que funcionó para archivos de alrededor de 100 MB pero arrojó Timeout error para archivos de 500 MB de tamaño. Así que me aseguré de usar Request Timeout como Infinite.

  2. Cargar archivo en trozos: Cargue un solo archivo como un conjunto de fragmentos con el StartUpload, ContinueUpload, y FinishUpload métodos en la clase File. No hay límites de tamaño de archivo. El tiempo de espera se produce después de 30 minutos. Cada fragmento del archivo debe cargarse dentro de los 30 minutos posteriores a la finalización del fragmento anterior para evitar el tiempo de espera. Recomendado para SharePoint Online cuando el archivo tiene más de 10 MB.

    Office Dev PnP ha proporcionado esta función en c #, simplemente la he convertido en PowerShell

    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)
        $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)
            $FileCreationInfo = New-Object Microsoft.SharePoint.Client.FileCreationInformation
            $FileCreationInfo.Overwrite = $true
            $FileCreationInfo.ContentStream = $FileStream
            $FileCreationInfo.URL = $UniqueFileName
            $Upload = $Docs.RootFolder.Files.Add($FileCreationInfo)
            $ctx.Load($Upload)
            $ctx.ExecuteQuery()
            return $Upload
        
        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, [System.IO.FileShare]::ReadWrite)
                $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
                        $Upload = $Docs.RootFolder.Files.Add($fileInfo)
                        $ctx.Load($Upload)
    
                        # 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 $_.Exception.Message -ForegroundColor Red
            
            Finally 
                if ($Fs -ne $null)
                
                    $Fs.Dispose()
                
            
        
        return $null
    
    

    Uso:

    $credentials = Get-Credential
    $SiteURL = "https://yoursite.sharepoint.com"
    $Context = New-Object Microsoft.SharePoint.Client.ClientContext($SiteURL) 
    $Context.Credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($credentials.UserName, $credentials.Password)
    
    $UpFile = UploadFileInSlice -ctx $Context -libraryName "YourLibName" -fileName "C:LargeFilesFileWithLargeSize.docx"
    

    Revisa este blog

Entonces, una vez que termine de cargar los archivos utilizando cualquiera de los métodos anteriores, puede cargar el objeto de archivo y cambiar las propiedades de los metedatos.

$File = $Context.Web.GetFileByServerRelativeUrl($fileUrl)
$ListItem = $File.ListItemAllFields
$Listitem["Field"] = "Value"
$ListItem.Update()
$Context.Load($ListItem)
$Context.ExecuteQuery()

El tamaño de la solicitud de CSOM de SharePoint es muy limitado y no puede superar el límite de 2 MB y no puede cambiar esta configuración en el entorno de Office 365. Entonces, si tiene que cargar archivos más grandes, debe usar la API REST. Aquí está la referencia de MSDN https://msdn.microsoft.com/en-us/library/office/dn292553.aspx

Reseñas y puntuaciones

Nos puedes añadir valor a nuestra información cooperando tu experiencia en las ilustraciones.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *