Get back to the business again! Just wanted to share another great things in SharePoint (although to user is not fun at all).
According to MSDN, there are a few options to upload files to SharePoint.
File upload option | Considerations | When should you use this? | Supported platforms |
Content property on the FileCreationInformation class. | Maximum file size that can be uploaded is 2 MB. Time-out occurs after 30 minutes. | Use to upload files that are less than 2 MB only. | SharePoint Server 2013, SharePoint Online |
SaveBinaryDirect method on the File class. | No file size limits. Time-out occurs after 30 minutes. | Only use this method if you're using a user-only authentication policy. User-only authentication policy is not available in an add-in for SharePoint, but can be used in native device apps, Windows PowerShell, and Windows console applications. | SharePoint Server 2013, SharePoint Online |
ContentStream property on the FileCreationInformation class. | No file size limits. Time-out occurs after 30 minutes. | Recommended for: | SharePoint Server 2013, SharePoint Online |
- SharePoint Server 2013. | |||
- SharePoint Online when the file is smaller than 10 MB. | |||
Upload a single file as a set of chunks using theStartUpload,ContinueUpload, andFinishUpload methods on the File class. | No file size limits. Time-out occurs after 30 minutes. Each chunk of the file must upload within 30 minutes of completion of the previous chunk to avoid the time-out. | Recommended for SharePoint Online when the file is larger than 10 MB. | SharePoint Online |
Now, here’s how you can upload large file to SharePoint in chunks.
[Cmdletbinding()]
param (
[Parameter(Mandatory=$true)]
[System.Object]$credential = $null,
[Parameter(Mandatory=$true)]
[System.String]$SiteUrl = $null,
[Parameter(Mandatory=$true)]
[System.String]$LibraryTitle = $null,
[Parameter(Mandatory=$false)]
[System.String]$UploadFolder = $null,
[Parameter(Mandatory=$true)]
[System.String]$FilePath = $null,
[Parameter(Mandatory=$false)]
[int]$ChunkSize = 10
)
function Using-Object
{
[CmdletBinding()]
param (
[Parameter(Mandatory = $true)]
[AllowEmptyString()]
[AllowEmptyCollection()]
[AllowNull()]
[Object]
$InputObject,
[Parameter(Mandatory = $true)]
[scriptblock]$ScriptBlock
)
try
{
. $ScriptBlock
}
catch
{
Write-Host $_.Exception.Message -ForegroundColor Red
}
finally
{
if ($null -ne $InputObject -and $InputObject -is [System.IDisposable])
{
$InputObject.Dispose()
}
}
}
Using-Object ($ctx = New-Object Microsoft.SharePoint.Client.ClientContext($SiteUrl)) {
#set the credentials, yada...yada...
if ($credential.GetType().Name -eq "SharePointOnlineCredentials") {
$ctx.Credentials = $credential
}
else {
$ctx.Credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($credential.UserName, $credential.Password)
}
# Each sliced upload requires a unique ID.
$UploadId = [GUID]::NewGuid()
# Get the name of the file.
$UniqueFileName = [System.IO.Path]::GetFileName($FilePath)
$SubWeb = $ctx.Web
$ctx.Load($SubWeb)
$ctx.ExecuteQuery()
# Get the folder to upload into.
$Docs = $SubWeb.Lists.GetByTitle($LibraryTitle)
$SubFolder = $Docs.RootFolder
$ctx.Load($Docs)
$ctx.Load($SubFolder)
$ctx.ExecuteQuery()
if ($UploadFolder)
{
$SubFolder = $SubWeb.GetFolderByServerRelativeUrl("$($SubFolder.ServerRelativeUrl)$($UploadFolder)")
$ctx.Load($SubFolder)
$ctx.ExecuteQuery()
}
# Get the information about the folder that will hold the file.
$ServerRelativeUrlOfRootFolder = $SubFolder.ServerRelativeUrl
# File object.
[Microsoft.SharePoint.Client.File]$upload
# Calculate block size in bytes.
$BlockSize = $ChunkSize * 1024 * 1024
# Get the size of the file.
$FileSize = (Get-Item $FilePath).length
if ($FileSize -le $BlockSize)
{
Write-Host "[$([System.DateTime]::Now.ToString("dd-MM-yyyy HH:mm:ss"))] Uploading '$($UniqueFileName)' (normal)"
# Use regular approach.
Using-Object ($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 = $UniqueFileName
$Upload = $SubFolder.Files.Add($FileCreationInfo)
$ctx.Load($Upload)
$ctx.ExecuteQuery()
#return $Upload
}
Write-Host "[$([System.DateTime]::Now.ToString("dd-MM-yyyy HH:mm:ss"))] File upload complete!"
}
else
{
# Use large file upload approach.
$BytesUploaded = $null
$Fs = $null
Try
{
$Fs = [System.IO.File]::Open($FilePath, [System.IO.FileMode]::Open, [System.IO.FileAccess]::Read, [System.IO.FileShare]::ReadWrite)
Using-Object ($br = New-Object System.IO.BinaryReader($Fs)) {
$buffer = New-Object System.Byte[]($BlockSize)
$lastBuffer = $null
$fileoffset = 0
$totalBytesRead = 0
$bytesRead
$first = $true
$last = $false
$chunkIndex = 0
$chunkName = "first"
Write-Host "[$([System.DateTime]::Now.ToString("dd-MM-yyyy HH:mm:ss"))] Uploading '$($UniqueFileName)' (chunks)"
# Read data from file system in blocks.
while(($bytesRead = $br.Read($buffer, 0, $buffer.Length)) -gt 0) {
$chunkIndex += 1
$totalBytesRead = $totalBytesRead + $bytesRead
# You've reached the end of the file.
if($totalBytesRead -eq $FileSize) {
$chunkName = "last"
$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 = $SubFolder.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()
$s.Dispose()
# fileoffset is the pointer where the next slice will be added.
$fileoffset = $BytesUploaded.Value
# You can only start the upload once.
$first = $false
$ContentStream.Dispose()
}
Else
{
# Get a reference to your file.
$Upload = $ctx.Web.GetFileByServerRelativeUrl($SubFolder.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()
$s.Dispose()
# Return the file object for the uploaded file.
#return $Upload
}
else {
$chunkName = "middle"
$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
$s.Dispose()
}
}
Write-Host "[$([System.DateTime]::Now.ToString("dd-MM-yyyy HH:mm:ss"))] Chunk $($chunkIndex) ($($chunkName)) finished"
if ($last) {
Write-Host "[$([System.DateTime]::Now.ToString("dd-MM-yyyy HH:mm:ss"))] File upload complete!"
}
}
}
}
Catch {
Write-Host $_.Exception.Message -ForegroundColor Red
}
Finally {
if ($Fs -ne $null)
{
$Fs.Dispose()
}
}
}
#return $null
}
Tidak ada komentar:
Posting Komentar
[give me your ideas, hopes, comments and compliments below...]
[aaand...... +1 if you need to....]