A long time ago I wrote about SharePoint 2007 Files Restore Tool, tool that allows you to connect to SharePoint content database (not need to have SharePoint installation) and extract documents.
The reason I wrote this tool was a customer that upgrade TFS and perform a new installation of SharePoint so he lost all his documents, this tool helped me to extract all documents and added them to the new SharePoint site.
SharePoint upgrade/migration can be unpleasant and sometimes I prefer to do a clean installation when upgrading or moving TFS and then just import the documents (without history).
Some customers wants to keep the history, so you can do small changes to download all file versions and then upload each version.
The big questions is how to extract all SharePoint documents from existing Site?
So, I’ve built another tool to help me do that, the below tool will connect to SharePoint using API and download all documents includes Folder structure to my computer.

Because I’m using SharePoint API you can write any Url of the SharePoint site, I’ll show the all documents folders includes files under each folder, and then you can click the download button to download all files or specific files to your machine.

How To Connect SharePoint Site:
* SharePoint API will only work on Machine with SharePoint installed *
public SPWeb _sp;
public void Connect()
{
try
{
using (SPSite site = new SPSite(txtSPUrl.Text))
{
TreeFolders.Items.Clear();
var webTree = new TreeViewItem();
webTree.Header = _sp.Title;
webTree.Tag = _sp;
MapFolders(_sp.Folders, webTree);
}
}
catch (Exception ex)
{
throw new ArgumentException("Connect", ex);
}
}
Building Folder Structure
I’ve created a recursive method to get the total number of files under a specific folder include all sub folders.
private int GetFilesCount(SPFolder folder, int count)
{
count += folder.Files.Count;
return folder.SubFolders.Aggregate(count, (current, subfolder) =>
GetFilesCount(subfolder, current));
}
private void MapFolders(SPFolderCollection folderList,
TreeViewItem treeNode)
{
for (var i = 0; i < folderList.Count; i++)
{
var item = new TreeViewItem();
item.Header = string.Format("{0} ({1})", folderList[i].Name,
GetFilesCount(folderList[i], 0));
item.Tag = folderList[i];
treeNode.Items.Add(item);
if (folderList[i].SubFolders.Count > 0)
MapFolders(folderList[i].SubFolders, item);
}
}
Download Files From SharePoint Folder
The CreateDirectoryStructure will build the local folder structure based on the file path in SharePoint, this is important because once we want to upload those files to a new SharePoint site we need those folder names in order to create them in the new SharePoint site.
Each SPFolder object contains a SPFileCollection with all files under that folder – Not include SubFolder files.
DownloadFile – will run over all files, get each file binary data and save the stream to a local file.
private void DownloadFile(SPFileCollection files)
{
foreach (SPFile file in files)
{
if (CreateDirectoryStructure(txtLocalPath.Text, file.Url))
{
var filepath = System.IO.Path.Combine(txtLocalPath.Text,
file.Url);
byte[] binFile = file.OpenBinary();
System.IO.FileStream fstream = System.IO.File.Create(filepath);
fstream.Write(binFile, 0, binFile.Length);
fstream.Close();
}
else
throw new ArgumentException("Cannot Create Folders Structure");
}
}
private bool CreateDirectoryStructure(string baseFolder, string filepath)
{
if (!Directory.Exists(baseFolder)) return false;
var paths = filepath.Split('/');
for (var i = 0; i < paths.Length - 1; i++)
{
baseFolder = System.IO.Path.Combine(baseFolder, paths[i]);
Directory.CreateDirectory(baseFolder);
}
return true;
}
Upload File To SharePoint Site
Once you got all files from the Old SharePoint site you can enter the new SharePoint site url and click the Upload button.
private void btnUpload_Click(object sender, RoutedEventArgs e)
{
using (SPSite site = new SPSite(txtTargetSP.Text))
{
SPWeb targetSP = site.OpenWeb();
foreach (var file in listLocalFolders.Items.Cast<string>().Select
(folder => Directory.GetFiles(folder, "*.*",
SearchOption.AllDirectories)).SelectMany(files => files))
{
UploadFile(file, file.Replace(txtLocalPath.Text, string.Empty)
, targetSP);
}
}
}
Removing the local path from the full file path will result with the destination file to the new SharePoint site.
The propose of EnsureParentFolder is to ensure the destination folder in the new SharePoint site exists, and if not create the folder in the new site.
UploadFile will stream out the file content and using SPWeb.Files.Add method include the destination path will add a new file to the SharePoint site.
public string EnsureParentFolder(SPWeb parentSite, string destinUrl)
{
destinUrl = parentSite.GetFile(destinUrl).Url;
var index = destinUrl.LastIndexOf("/");
var parentFolderUrl = string.Empty;
if (index > -1)
{
parentFolderUrl = destinUrl.Substring(0, index);
SPFolder parentFolder
= parentSite.GetFolder(parentFolderUrl);
if (!parentFolder.Exists)
{
SPFolder currentFolder = parentFolderUrl.Split('/').
Aggregate<string, SPFolder>(parentSite.RootFolder,
(current, folder) => current.SubFolders.Add(folder));
}
}
return parentFolderUrl;
}
public void UploadFile(string srcUrl, string destUrl, SPWeb site)
{
if (!File.Exists(srcUrl))
{
throw new ArgumentException(String.Format("{0} does not exist",
srcUrl), "srcUrl");
}
var fStream = File.OpenRead(srcUrl);
var contents = new byte[fStream.Length];
fStream.Read(contents, 0, (int)fStream.Length);
fStream.Close();
if (destUrl.StartsWith("\\"))
destUrl = destUrl.Substring(1);
destUrl = destUrl.Replace("\\", "/");
EnsureParentFolder(site, destUrl);
try
{
site.Files.Add(destUrl, contents, true);
}
catch (Exception ex)
{
}
}
Enjoy