CSOM. Загрузка файлов
Пример загрузки документов в библиотеку SharePoint с помощью клиентской модели SharePoint .NET (CSOM).
Это простое консольное приложение созданное с помощью Visual Studio 2017, которое работает со следующими версиями SharePoint:
- SharePoint 2013
- SharePoint 2016
- SharePoint 2019
- SharePoint Online
Теоретически должно работать и с SharePoint 2010. Я не проверял - нет под рукой разработческого SharePoint.
Консольное приложение
Запускаем Visual Studio и создаем новый проект - Консольное приложение (.NET Framework):
После того как приложение создано необходимо добавить ссылки на сборки для работы с SharePoint.
Существуют как минимум два способы сделать это:
Добавить ссылку на существующую сборку Microsoft.SharePoint.Client.dll, которая расположена в папке %ProgramFiles%\Common Files\Microsoft Shared\web server extensions**{15|16}**\ISAPI (если есть установленный SharePoint).
Второй способ - добавление nuget-пакета, выпущенного компанией Microsoft.
В демонстрационном проекте я использовал NuGet.
NuGet Пакет
Чтобы установить пакет Microsoft.SharePointOnline.CSOM, который содержит CSOM-библиотеки как для SharePoint, так и для Project Server/Online, просто выполните следующую команду в консоле управления пакетами:
PM> Install-Package Microsoft.SharePointOnline.CSOM
Всё необходимое есть, теперь можно создавать код.
ClientContext
Для работы с SharePoint с помощью CSOM необходимо инициализировать объект ClientContext:
// URL-адрес сайта SharePoint
var siteUrl = "https://sharepointsiteurl";
using (var ctx = new ClientContext(siteUrl))
{
// Код для работы с SharePoint
}
Перед тем как выполнять какие-либо операции необходимо предоставить учетные данные.
Учетные данные в ClientContext
Свойство Credentials должно быть представлено объектом, который реализует интерфейс ICredential:
Таких классов несколько:
- System.Net.CredentialCache
- System.Net.NetworkCredential
- Microsoft.SharePoint.Client.SharePointOnlineCredentials
- Microsoft.SharePoint.IdentityModel.OAuth2.OAuth2BearerCredentials
Используйте класс SharePointOnlineCredentials для работы с SharePoint Online и NetworkCredential в остальных случаях.
Если Вы попробуете использовать SharePointOnlineCredentials для работы с on-premise SharePoint, то будет выброшено такое исключение:
Microsoft.SharePoint.Client.ClientRequestException: The IDCRL response header from server '{SharePointSiteUrl}' 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'.
Или такое:
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.NET
В консольном приложении, в случае если SharePointOnlineCredentials не сработал (значит мы работаем с on-premise SharePoint), то свойство Credentials заменяется на объект типа NetworkCredential:
// URL-адрес сайта SharePoint
var siteUrl = "https://sharepointsiteurl";
// Логин
var userLogin = "userLogin@domain";
// Пароль
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
{
// Пробуем использовать SharePoint Online Credentials
ctx.Credentials = SPOCredentials;
ctx.ExecuteQuery();
}
catch (ClientRequestException)
{
// переключаемся на NetworkCredential
ctx.Credentials = SPCredentials;
ctx.ExecuteQuery();
}
catch (NotSupportedException)
{
// переключаемся на NetworkCredential
ctx.Credentials = SPCredentials;
ctx.ExecuteQuery();
Console.WriteLine("SharePoint On-premise");
}
// Код для работы с SharePoint
}
Теперь приложение будет работать как с on-premise SharePoint, так и с SharePoint Online (или Project Online).
Документ
Документ генерируется при исполнении приложения в памяти. Это простой текстовый файл:
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(@"Съешь ещё этих мягких французских булок, да выпей чаю");
}
fileBytes = ms.ToArray();
}
}
Загрузка документы
Для загрузки необходимо инициализировать объект типа FileCreationInformation:
// Информация о документе
var fileInformation = new FileCreationInformation
{
// Относительный URL загружаемого файла
Url = library.RootFolder.ServerRelativeUrl + "/fileName2.txt",
// Перезаписываем файл, если он уже есть
Overwrite = true,
// Содержимое файла
Content = fileBytes
};
// Добавляем файл в корневую папку библиотеки документов
library.RootFolder.Files.Add(fileInformation);
ctx.ExecuteQuery();
Это был первый способ и у него есть ограничение: максимальный размер файла 2 МБ. Если файл больше двух мегабайт, то получим исключение:
Microsoft.SharePoint.Client.ServerException: 'The request message is too big. The server does not allow messages larger than 2097152 bytes.'
Для этого есть второй способ загрузить документ.
Загрузка большого документа
Для больших файлов существует метод SaveBinaryDirect класса Microsoft.SharePoint.Client.File:
Microsoft.SharePoint.Client.File.SaveBinaryDirect(
//Контекст
ctx,
// Относительный URL загружаемого файла
library.RootFolder.ServerRelativeUrl + "/fileName2.txt",
// Содержимое файла
new MemoryStream(fileBytes),
// Перезаписываем файл, если он уже есть
true);
ctx.ExecuteQuery();
Даже если загружаемый документ слишком большой - есть выход в CSOM.
Загрузка документа по частям
Для загрузки файла по частям существует набор методов в классе Microsoft.SharePoint.Client.File:
- StartUpload
- ContinueUpload
- FinishUpload
- CancelUpload
Начинаем загрузку с помощью метода StartUpload, затем продолжаем загрузку с помощью метода ContinueUpload и завершаем загрузку вызовом метода FinishUpload. Если необходимо прервать загрузку - вызываем метод CancelUpload.
Сначала создаем пустой файл и только после этого начинаем загрузку его контента:
// Создаем пустой файл
var fileChunkedInformation = new FileCreationInformation
{
// Относительный URL загружаемого файла
Url = library.RootFolder.ServerRelativeUrl + "/fileName3.txt",
// Перезаписываем файл, если он уже есть
Overwrite = true,
Content = new byte[] {}
};
// Добавляем файл в корневую папку библиотеки документов
var fileChunked = library.RootFolder.Files.Add(fileChunkedInformation);
ctx.ExecuteQuery();
// Идентификатор загрузки
var uploadId = Guid.NewGuid();
// Смещение в массиве содержимого файла
var fileBytesOffset = 0;
// Смещение в загружаемом файле
long fileChunkedOffset = 0;
// Размер загружаемой части
var fileChunkArrayBuffer = new byte[1024];
while (fileBytesOffset < fileBytes.Length)
{
// Длина массива, который будет загружен
var length = Math.Min(fileChunkArrayBuffer.Length, fileBytes.Length - fileBytesOffset);
// Копируем часть массива в буфер
Buffer.BlockCopy(fileBytes, fileBytesOffset, fileChunkArrayBuffer, 0, length);
// Буфер в Stream
using (var ms = new MemoryStream(fileChunkArrayBuffer))
{
// Если смещение равно 0 - Начинаем загрузку
if (fileChunkedOffset == 0)
{
var fileChunkedOffsetResult = fileChunked.StartUpload(uploadId, ms);
ctx.ExecuteQuery();
fileChunkedOffset = fileChunkedOffsetResult.Value;
}
// Продолжаем загрузку
else if (fileBytesOffset + length <= fileBytes.Length)
{
var fileChunkedOffsetResult = fileChunked.ContinueUpload(uploadId, fileChunkedOffset, ms);
ctx.ExecuteQuery();
fileChunkedOffset = fileChunkedOffsetResult.Value;
}
// Последняя часть файла - завершаем загрузку
else
{
fileChunked.FinishUpload(uploadId, fileChunkedOffset, ms);
ctx.ExecuteQuery();
}
}
fileBytesOffset += length;
}
И результат:
Исходные коды
Исходные коды доступны здесь: https://code.msdn.microsoft.com/Upload-document-to-32056dbf.
Ссылки
Complete basic operations using SharePoint client library code