CSOM. Upload document
Sample how to upload documents to SharePoint document library with SharePoint .NET client object model CSOM (Client-Side Object Model).
Example project is a simple Console Application created in Visual Studio 2017. This application can be able to work with most of existing SharePoint versions:
- SharePoint 2013
- SharePoint 2016
- SharePoint 2019
- SharePoint Online
Even SharePoint 2010 is not a problem. I just have no developer instance of this version of SharePoint for testing.
Console Application
Run Visual Studio and add new Console App (.NET Framework):
After application is created we need to add necessary references to work with SharePoint.
There are at least two ways to add the reference to the project:
Add link to existing Microsoft.SharePoint.Client.dll assembly located in %ProgramFiles%\Common Files\Microsoft Shared\web server extensions\15|16\ISAPI folder (if you have installed SharePoint on-premise instance).
The second way is adding special nuget-package released by Microsoft.
In this sample project I use nuget.
Nuget Package
To install Microsoft.SharePointOnline.CSOM package which contains both SharePoint and Project CSOM libraries just run the following command in Package Manager console:
PM> Install-Package Microsoft.SharePointOnline.CSOM
All necessary references added and now we can add some value.
ClientContext
To interact with SharePoint via CSOM we need to initialize ClientContext
// SharePoint Site URL
var siteUrl = "https://sharepointsiteurl";
using (var ctx = new ClientContext(siteUrl))
{
// Working with SharePoint Data
}
Before performing any CSOM operation you need to provide credentials.
ClientContext Credentials
Credentials property must be presented with class implementing ICredential interface:
There are some such classes:
- System.Net.CredentialCache
- System.Net.NetworkCredential
- Microsoft.SharePoint.Client.SharePointOnlineCredentials
- Microsoft.SharePoint.IdentityModel.OAuth2.OAuth2BearerCredentials
Use SharePointOnlineCredentials for SharePoint Online and NetworkCredential in other case.
If you'll try to use SharePointOnlineCredentials to interact with on-premise SharePoint the following exception will be thrown:
Microsoft.SharePoint.Client.ClientRequestException: The IDCRL response header from server '' is not valid. The response header value is 'NTLM'. The response status code is 'Unauthorized'. All response headers are 'SPRequestDuration=3, SPIisLatency=0, MicrosoftSharePointTeamServices=16.0.0.10711: 1; RequireReadOnly, Content-Length=16, Content-Type=text/plain; charset=utf-8, Date=Fri, 27 Jul 2018 14:53:07 GMT, Server=Microsoft-IIS/10.0, WWW-Authenticate=NTLM, X-Powered-By=nosniff'.
Or something like the following:
System.NotSupportedException: Cannot contact web site '' or the web site does not support SharePoint Online credentials. The response status code is 'OK'. The response headers are
X-SharePointHealthScore=4,
SPRequestGuid=74ee7e9e-8c75-309f-b9c2-2db7076e60a4,
request-id=74ee7e9e-8c75-309f-b9c2-2db7076e60a4,
X-FRAME-OPTIONS=SAMEORIGIN,
SPRequestDuration=460,
SPIisLatency=0,
MicrosoftSharePointTeamServices=16.0.0.4327,
X-AspNet-Version=4.0.30319,
X-Powered-By=ASP.NETv
In the sample app if SharePointOnlineCredentials does not work (it means we work with on-premise SharePoint) Credentials replaced with NetworkCredential:
// SharePoint Site URL
var siteUrl = "https://sharepointsiteurl";
// Login
var userLogin = "userLogin@domain";
// Password
var userPassword = "P@ssw0rd";
var pwd = new SecureString();
foreach (var c in userPassword) pwd.AppendChar(c);
var SPOCredentials = new SharePointOnlineCredentials(userLogin, pwd);
var SPCredentials = new NetworkCredential(userLogin, pwd);
using (var ctx = new ClientContext(siteUrl))
{
try
{
// try to use SharePoint Online Credentials
ctx.Credentials = SPOCredentials;
ctx.ExecuteQuery();
}
catch (ClientRequestException)
{
// switch to NetworkCredential
ctx.Credentials = SPCredentials;
ctx.ExecuteQuery();
}
catch (NotSupportedException)
{
// switch to NetworkCredential
ctx.Credentials = SPCredentials;
ctx.ExecuteQuery();
Console.WriteLine("SharePoint On-premise");
}
// Working with SharePoint Data
}
For the sample app it does not matter what the version of SharePoint (or Project Online) is on other side.
Document
Document for uploading generated in runtime. It's just a text file:
var fileBytes = new byte[] { };
using (var ms = new MemoryStream())
{
using (TextWriter tw = new StreamWriter(ms, Encoding.UTF8))
{
for (var i = 0; i < 100; i++)
{
tw.WriteLine(@"The quick brown fox jumps over the lazy dog");
}
fileBytes = ms.ToArray();
}
}
Upload Document
For uploading we need to provide an object of type FileCreationInformation:
// Information about the file
var fileInformation = new FileCreationInformation
{
// Server relative url of the document
Url = library.RootFolder.ServerRelativeUrl + "/fileName2.txt",
// Overwrite file if it's already exist
Overwrite = true,
// Content of the file
Content = fileBytes
};
// Upload the file to root folder of the Document library
library.RootFolder.Files.Add(fileInformation);
ctx.ExecuteQuery();
It was first approach. And it has a limitation: maximum file size is 2MB. If file size is greater than 2MB CSOM raises an exception:
Microsoft.SharePoint.Client.ServerException: 'The request message is too big. The server does not allow messages larger than 2097152 bytes.'
For this case there is another approach to upload a document.
Upload Large Document
For large file uploading there is a SaveBinaryDirect method of Microsoft.SharePoint.Client.File class:
Microsoft.SharePoint.Client.File.SaveBinaryDirect(
//Client Context
ctx,
// Server relative url of the document
library.RootFolder.ServerRelativeUrl + "/fileName2.txt",
// Content of the file
new MemoryStream(fileBytes),
// Overwrite file if it's already exist
true);
ctx.ExecuteQuery();
Even your document is extremely large there is an approach in CSOM.
Chunked Upload Document
If your file is large or you just want to upload a document by chunk there is a set of methods in Microsoft.SharePoint.Client.File class:
- StartUpload
- ContinueUpload
- FinishUpload
- CancelUpload
We start uploading using StartUpload method, then continue uploading with ContinueUpload method and complete uploading with FinishUpload. If you do not want to finish uploading - call CancelUpload method.
First of all we create empty file and only after that start uploading the content:
// Create empty chunked file
var fileChunkedInformation = new FileCreationInformation
{
// Server relative url of the document
Url = library.RootFolder.ServerRelativeUrl + "/fileName3.txt",
// Overwrite file if it's already exist
Overwrite = true,
Content = new byte[] {}
};
// Upload the file to root folder of the Document library
var fileChunked = library.RootFolder.Files.Add(fileChunkedInformation);
ctx.ExecuteQuery();
// Upload Id
var uploadId = Guid.NewGuid();
// Offset of the byte array (file content)
var fileBytesOffset = 0;
// Offset of the uploaded file
long fileChunkedOffset = 0;
// Size of a chunk
var fileChunkArrayBuffer = new byte[1024];
while (fileBytesOffset < fileBytes.Length)
{
// How many bytes will be read from file content
var length = Math.Min(fileChunkArrayBuffer.Length, fileBytes.Length - fileBytesOffset);
// Copy bytes to buffer array
Buffer.BlockCopy(fileBytes, fileBytesOffset, fileChunkArrayBuffer, 0, length);
// Buffer array to stream
using (var ms = new MemoryStream(fileChunkArrayBuffer))
{
// If the offset equals 0 - Start Upload
if (fileChunkedOffset == 0)
{
var fileChunkedOffsetResult = fileChunked.StartUpload(uploadId, ms);
ctx.ExecuteQuery();
fileChunkedOffset = fileChunkedOffsetResult.Value;
}
// Continue uploading
else if (fileBytesOffset + length <= fileBytes.Length)
{
var fileChunkedOffsetResult = fileChunked.ContinueUpload(uploadId, fileChunkedOffset, ms);
ctx.ExecuteQuery();
fileChunkedOffset = fileChunkedOffsetResult.Value;
}
// Last chunk- Finish uploading
else
{
fileChunked.FinishUpload(uploadId, fileChunkedOffset, ms);
ctx.ExecuteQuery();
}
}
fileBytesOffset += length;
}
And the result:
Source Code
Source code located here: https://code.msdn.microsoft.com/Upload-document-to-32056dbf.
Links
Complete basic operations using SharePoint client library code