How to download/upload files from/to SharePoint 2013 using CSOM?
I am developing a Win8 (WinRT, C#, XAML) client application (CSOM) that needs to download/upload files from/to SharePoint 2013.
How do I do the Download/Upload?
Solution 1:
Upload a file
Upload a file to a SharePoint site (including SharePoint Online) using File.SaveBinaryDirect Method:
using (var clientContext = new ClientContext(url))
{
using (var fs = new FileStream(fileName, FileMode.Open))
{
var fi = new FileInfo(fileName);
var list = clientContext.Web.Lists.GetByTitle(listTitle);
clientContext.Load(list.RootFolder);
clientContext.ExecuteQuery();
var fileUrl = String.Format("{0}/{1}", list.RootFolder.ServerRelativeUrl, fi.Name);
Microsoft.SharePoint.Client.File.SaveBinaryDirect(clientContext, fileUrl, fs, true);
}
}
Download file
Download file from a SharePoint site (including SharePoint Online) using File.OpenBinaryDirect Method:
using (var clientContext = new ClientContext(url))
{
var list = clientContext.Web.Lists.GetByTitle(listTitle);
var listItem = list.GetItemById(listItemId);
clientContext.Load(list);
clientContext.Load(listItem, i => i.File);
clientContext.ExecuteQuery();
var fileRef = listItem.File.ServerRelativeUrl;
var fileInfo = Microsoft.SharePoint.Client.File.OpenBinaryDirect(clientContext, fileRef);
var fileName = Path.Combine(filePath,(string)listItem.File.Name);
using (var fileStream = System.IO.File.Create(fileName))
{
fileInfo.Stream.CopyTo(fileStream);
}
}
Solution 2:
This article describes various options for accessing SharePoint content. You have a choice between REST and CSOM. I'd try CSOM if possible. File upload / download specifically is nicely described in this article.
Overall notes:
//First construct client context, the object which will be responsible for
//communication with SharePoint:
var context = new ClientContext(@"http://site.absolute.url")
//then get a hold of the list item you want to download, for example
var list = context.Web.Lists.GetByTitle("Pipeline");
var query = CamlQuery.CreateAllItemsQuery(10000);
var result = list.GetItems(query);
//note that data has not been loaded yet. In order to load the data
//you need to tell SharePoint client what you want to download:
context.Load(result, items=>items.Include(
item => item["Title"],
item => item["FileRef"]
));
//now you get the data
context.ExecuteQuery();
//here you have list items, but not their content (files). To download file
//you'll have to do something like this:
var item = items.First();
//get the URL of the file you want:
var fileRef = item["FileRef"];
//get the file contents:
FileInformation fileInfo = File.OpenBinaryDirect(context, fileRef.ToString());
using (var memory = new MemoryStream())
{
byte[] buffer = new byte[1024 * 64];
int nread = 0;
while ((nread = fileInfo.Stream.Read(buffer, 0, buffer.Length)) > 0)
{
memory.Write(buffer, 0, nread);
}
memory.Seek(0, SeekOrigin.Begin);
// ... here you have the contents of your file in memory,
// do whatever you want
}
Avoid working with the stream directly, read it into the memory first. Network-bound streams are not necessarily supporting stream operations, not to mention performance. So, if you are reading a pic from that stream or parsing a document, you may end up with some unexpected behavior.
On a side note, I have a related question re: performance of this code above, as you are taking some penalty with every file request. See here. And yes, you need 4.5 full .NET profile for this.