Tuesday, 18 February 2014

Time to backup SkyDrive


It has been a long time since I last blogged. I tried out the Azure WordPress blog but was a little disappointed. The layout was not as wide as in this blog which is a problem if you want to cut and paste some code. Also I did not like the idea of storing a password, I would have preferred delegated security using an identity provider like facebook or LiveId. So I will continue here...

I have been using SkyDrive quite extensively. Although it's on very robust hardware there is always a danger that you can accidently delete something. I did not want to install SkyDrive on my virtual PC but I wanted to download the contents of my SkyDrive. So I made a little program to copy all the files to a file store. I used code from http://skydriveapiclient.codeplex.com/releases/view/103081, here's the class that does the work. Using the above library meant that I did not have to setup oAuth, instead I used my E-Mail and Password and the SkyDriveClient deals with the oAuth for me.

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.Serialization.Formatters.Binary;
using System.Text;
using System.Threading.Tasks;
using HgCo.WindowsLive.SkyDrive;

namespace SkyDrive
{
    public class Sky
    {
        private string Email;
        private string Password;
        private string RestorePath;
        public Sky(string Email, string Password, string RestorePath)
        {
            this.Email = Email;
            this.Password = Password;
            this.RestorePath = RestorePath;
        }

        public void BackupTree()
        {
            var client = new SkyDriveServiceClient();
            client.LogOn(this.Email, this.Password);

            // Get root directory
            WebFolderInfo wfInfo = new WebFolderInfo();
            WebFolderInfo[] wfInfoArray = client.ListRootWebFolders();
            client.Timeout = 1000000000;

            foreach (WebFolderInfo dir in wfInfoArray)
            {
                Console.WriteLine(dir.Path);
                CopyTree(client, dir, this.RestorePath + @"\" + dir.Name);
            }
        }

        private void CopyTree(SkyDriveServiceClient client, 
                           WebFolderInfo subDir, string HardDiskPath)
        {
            if (!Directory.Exists(HardDiskPath))
            {
                Directory.CreateDirectory(HardDiskPath);
            }

            WebFileInfo[] files = client.ListSubWebFiles(subDir);
            foreach (WebFileInfo f in files)
            {
                using (Stream sr = client.DownloadWebFile(f))
                {
                    string fileName = HardDiskPath + @"\" + f.Name;
                    if (!File.Exists(fileName))
                    {
                        using (FileStream fs = new FileStream(HardDiskPath 
                                      + @"\" + f.Name, FileMode.OpenOrCreate))
                        {
                            byte[] buffer = new byte[64 * 1024];
                            int count = 0;
                            while ((count = sr.Read(buffer, 0, buffer.Length)) > 0)
                                fs.Write(buffer, 0, count);
                        }
                    }
                }
            }

            WebFolderInfo[] wfSubInfoArray = client.ListSubWebFolders(subDir);
            foreach (WebFolderInfo dir in wfSubInfoArray)
            {
                Console.WriteLine(dir.Path);
                string sDir = HardDiskPath + @"\" + dir.Name;
                CopyTree(client, dir, sDir);
            }
        }
    }
}

Here are some other links for the RESTful interface to SkyDrive
Interactive SDK http://isdk.dev.live.com/dev/isdk/Default.aspx?mkt=en-us
SDK http://msdn.microsoft.com/en-US/live/ff621310