Programmatically download a SharePoint document library in .NET

In this post I will show you a simple, but yet very useful piece of code that downloads an entire SharePoint document library to local disk drive. Many of our customers need to export and publish SharePoint documents externally, sometimes involving programmatic processing and manipulation. Others just do this regularly for keeping backups. This example helps you getting started and also show how to use the Modified date of documents to sharpen the performance of your application.

Requirements

This example project can be downloaded here!

Download example!

Building the application

In this example, we will create a simple console application that queries a SharePoint document library for all its documents and folders and then iterates through the results. The entire structure will then be reconstructed on local disk, including empty folders. We will also compare the Modified date of each document with the last write time of the corresponding local file to decided whether a document needs to be updated. This may increase the performance significantly when doing large backups.

In Visual Studio 2010, create a new Console Application (C#) and call it DownloadDocumentLibraryExample.

  

Open up Program.cs and replace the content with the following lines. You will also need to add a reference to the Camelot.SharePointConnector.dll, found in the global assembly cache.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Camelot.SharePointConnector.Data;
using System.IO;

namespace DownloadDocumentLibraryExample
{
    class Program
    {
        static void Main(string[] args)
        {
            var connectionString = "Server=mysharepointserver.com;Database=;User=user;Password=password;Authentication=Ntlm;TimeOut=60;";
            var rootFolder = @"c:documents";

            var documents = Helper.ExecuteDataTable("SELECT ServerUrl, Modified, ContentType FROM `Shared Documents`", connectionString);
            if (documents.Rows.Count > 0)
            {
                foreach (System.Data.DataRow doc in documents.Rows)
                {
                    Console.WriteLine(doc["ContentType"] + "  " + doc["ServerUrl"]);

                    using (var connection = new SharePointConnection(connectionString))
                    {
                        connection.Open();

                        switch ((string)doc["ContentType"])
                        {
                            case "Folder":
                                if (!Directory.Exists(rootFolder + doc["ServerUrl"]))
                                    Directory.CreateDirectory(rootFolder + doc["ServerUrl"]);

                                break;
                            case "Document":
                                var parentFolder = Directory.GetParent(rootFolder + doc["ServerUrl"]).ToString();

                                if (!Directory.Exists(parentFolder))
                                    Directory.CreateDirectory(parentFolder);

                                if (!File.Exists(rootFolder + doc["ServerUrl"]) || File.GetLastWriteTime(rootFolder + doc["ServerUrl"]) != (DateTime)doc["Modified"])
                                {
                                    using (var command = new SharePointCommand("CALL DOWNLOAD('Shared Documents', '" + doc["ServerUrl"] + "')", connection))
                                    {
                                        var bytes = (byte[])command.ExecuteScalar();
                                        File.WriteAllBytes(rootFolder + doc["ServerUrl"], bytes);
                                        File.SetLastWriteTime(rootFolder + doc["ServerUrl"], (DateTime)doc["Modified"]);
                                    }
                                }

                                break;
                        }

                    }
                }
            }
            Console.WriteLine("Complete!");
            Console.ReadKey();
        }
    }
}

Firstly, we declare our SharePoint connection string required for connecting to the SharePoint server. You will need to modify the connection string in the example according to your configuration. The template in the example should work fine in most cases but all options are described in the connector documentation. Secondly, we declare a root folder where all documents will be downloaded, e.g. “c:\documents”.

Now we are ready to query the document library. For simplicity in this example, we choose to download the Shared Documents library. Our query selects all items in this library returning the ServerUrl, Modified and ContentType columns. The first column indicates the relative path of a document or folder, e.g. “textfile.txt” or “folder1/folder2/textfile.txt”, giving us the structure of the library. It will be printed to the console window. The ContentType can be either “Folder” or “Document”. Note that we use the ExecuteDataTable method in the Helper class to select directly into a DataTable.

In the next step, we iterate through the items returned by the select query. If the item is of type “Folder”, we simply create the folder under the root folder. If the item is of type “Document”, we first compare the date of any existing file with the SharePoint Modified date to determine if the document has changed since it was last downloaded. If it has, we use the DOWNLOAD procedure of the Camelot .NET Connector to fetch the file and then write it to disk.

Running the application

Now run the application and see what happens. If everything goes fine and there are documents and/or folders in the library, you should see a list of items as they are being processed. When the application is done you should find the documents in your root folder.

  

If you run the application a second time, you probably notice that documents are not being downloaded again until they have been modified.

This entry was posted in Camelot .NET Connector, General, Integrations, SharePoint. Bookmark the permalink.

5 Responses to Programmatically download a SharePoint document library in .NET

  1. Abed Habboub says:

    please advice
    i am encountering the following when trying to compile my application:

    The referenced assembly “Camelot.SharePointConnector, Version=2.0.0.0, Culture=neutral, PublicKeyToken=df3b3837162a8b6c, processorArchitecture=MSIL” could not be resolved because it has a dependency on “System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a” which is not in the currently targeted framework “.NETFramework,Version=v4.0,Profile=Client”. Please remove references to assemblies not in the targeted framework or consider retargeting your project.

  2. Abed Habboub says:

    that is fine. i solved it.

  3. Abdallah Nassar says:

    Kindly elaborate if it is possible to extract site columns values associated with each exported document? Is there a way to do this if it’s not supported by the package?

    • Eric Herlitz says:

      I assume you are using the CALL DOWNLOAD procedure and then it’s not supported. This will require two different queries

      SELECT * FROM `Document Library` WHERE LinkFilename = ‘yourfile.docx’
      CALL DOWNLOAD(‘Document Library’, ‘yourfile.docx’)

      It is this way since there is no way to retrieve lite item data along with the binary stream from SharePoint.

  4. Vlad says:

    Hi,
    I need to download ALL versions of the document. Is it possible?
    Thanks

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>