Tuesday, November 8, 2011

How to upload and download documents using the client object model

With the increasing popularity of SharePoint 2010, and especially after the introduction of Office365, the market for client applications for SharePoint is increasing. In response, Microsoft has released the SharePoint Client Object Model, which is a wrapper library for the SharePoint web services.

In this post I will demonstrate how you can use the Client Object Model (dare we use the abbreviation COM?) to upload and download files to and from SharePoint. This may prove a central operation if you are migrating an existing SharePoint site to Office365. Other scenarios include uploading an existing file store to document libraries in a local SharePoint farm, or creating plug-in's to existing applications that need to process your documents.

The client context

The central class for the client code is the ClientContext. An instance of this class defines the connection to SharePoint, and any request, whether for getting or setting data, passes through the ClientContext instance. The general procedure is as folows:

  1. Define the requests you need to make using objects from the Client Object Model.
  2. Use the client context instance to execute the requests and load the data from SharePoint.
  3. Perform any processing of the data on the client side.
  4. (Optional) Use the client context instance to re-submit the data into SharePoint.
You can reuse the client context instance for multiple requests.

Downloading documents

To download documents you need to know the URL to the document. This is stored in the document list item as item["FileRef"], or you may just happen to know what it is. No matter how we get it, we need the server-relative URL to the document. Once we have that, we can download the document with just a few lines of client code:

string fileRef = item["FileRef"].ToString();
string fileName = fileRef.Substring(fileRef.LastIndexOf('/') + 1);
using (FileInformation fileInfo = File.OpenBinaryDirect(myContext, fileRef))
{
  using (IO.FileStream writeStream = IO.File.Open(@"c:\MyFolder\" + fileName, IO.FileMode.Create))
  {
    fileInfo.Stream.CopyTo(writeStream);
    writeStream.Flush();
  }
}

Of course you can name the document whatever you want. The above is just a simple way of getting the original file name.

Uploading documents

Uploading the document is not much more difficult than downloading it. In general, when we create things with the client object model, we need to make some kind of creation information object. For documents (and files in general) the class to use is the FileCreationInformation class.

FileCreationInformation myCreateInfo =
  new FileCreationInformation();
createInfo.Content = System.IO.File.ReadAllBytes(@"c:\MyFolder\MyDocument.docx");
createInfo.Url = "MyDocument.docx";
File myFile = myLibrary.RootFolder.Files.Add(myCreateInfo);
myContext.Load(myFile);
myContext.ExecuteQuery();

This code will upload the document to the root folder of the document library. If you are not satisfied with this, you can find the desired folder by iterating through the folders and sub-folders using myLibrary.RootFolder.Folders.

Setting document metadata

Often we need to set some metadata on the documents. This can be achieved by using the list item connected to the file. Continuing from the code in the previous section:

ListItem myItem = myFile.ListItemAllFields;
myItem["myField"] = "myFieldvalue"]
//... set additional fields

myItem.Update();
myContext.ExecuteQuery();

You can add whatever fields you like. Just be sure to use the internal name of the field.

Summing it up

With the code above we can download files - documents, images, or anything - from SharePoint libraries. We can also upload files, and set their metadata.

The code works against any version of SharePoint, even SharePoint Online (as part of Office365). The last, however, requires the use of Live-ID when login in. In an upcoming post I will describe how to do this.

2 comments:

  1. Was going through the comments at http://www.wictorwilen.se/Post/How-to-do-active-authentication-to-Office-365-and-SharePoint-Online.aspx and noticed that you were wondering how to automatically authenticate federated users as part of SharePoint Online. Have you had any luck figuring this out? I'm having the same issue and am trying to find out if this is even possible.

    Thanks!
    Drew Haubrich
    dhaubrich@paradigm.sk.ca

    ReplyDelete
  2. Hi Drew

    I didn't find a solution to the fully automatic authentication against ADFS. So far my leads point in the direction that this is not currently supported.

    By using this code and also the comment by Guillermo Bas I was able to make a solution that required the user to do the initial login. For any subsequent calls the cookie thus obtained could be reused.

    So if your application makes requests to SharePoint Online with sufficiently small intervals then you can get away with having to login at the application startup. The cookie will then be reused and renewed on subsequent calls.

    So the end result was that the user had to login when the application was started, but afterwards the application could proceed unattended, as long as the cookie did not expire.

    ReplyDelete