250 lines
9.5 KiB
C#
250 lines
9.5 KiB
C#
using System;
|
|
using System.IO;
|
|
using System.Text;
|
|
using AppLimit.CloudComputing.SharpBox.SyncFramework;
|
|
|
|
namespace AppLimit.CloudComputing.SharpBox
|
|
{
|
|
public partial class CloudStorage
|
|
{
|
|
/// <summary>
|
|
/// This flags are used to control the folder
|
|
/// synchronization.
|
|
/// </summary>
|
|
[Flags]
|
|
public enum SyncFolderFlags
|
|
{
|
|
/// <summary>
|
|
/// Place holder for empty
|
|
/// </summary>
|
|
Empty = 0x00000000,
|
|
|
|
/// <summary>
|
|
/// Just upload file from local to remote
|
|
/// </summary>
|
|
UploadItems = 0x00000001,
|
|
|
|
/// <summary>
|
|
/// Just download files from remote to local
|
|
/// </summary>
|
|
DownloadItems = 0x00000002,
|
|
|
|
/// <summary>
|
|
/// Remove files which are not available in remote
|
|
/// </summary>
|
|
RemoveMissingFiles = 0x00000004,
|
|
|
|
/// <summary>
|
|
/// Performe the action recursively
|
|
/// </summary>
|
|
Recursive = 0x00000008,
|
|
|
|
/// <summary>
|
|
/// Synchronize all, which combines the right flags
|
|
/// </summary>
|
|
Synchronize = UploadItems | DownloadItems | RemoveMissingFiles | Recursive
|
|
}
|
|
|
|
/// <summary>
|
|
/// This function allows to synchronize a local folder with an folder exists in the cloud storage
|
|
/// and vice versa. The local folder and the target folder has to be created before.
|
|
/// </summary>
|
|
/// <param name="srcFolder"></param>
|
|
/// <param name="tgtFolder"></param>
|
|
/// <param name="flags"></param>
|
|
/// <returns></returns>
|
|
public bool SynchronizeFolder(DirectoryInfo srcFolder, ICloudDirectoryEntry tgtFolder, SyncFolderFlags flags)
|
|
{
|
|
// init ret value
|
|
var bRet = true;
|
|
|
|
// init helper parameter
|
|
var bRecursive = ((flags & SyncFolderFlags.Recursive) != 0);
|
|
|
|
// init the differ
|
|
var diff = new DirectoryDiff(srcFolder, tgtFolder);
|
|
|
|
// build the diff results
|
|
var res = diff.Compare(bRecursive);
|
|
|
|
// process the diff result
|
|
foreach (var item in res)
|
|
{
|
|
switch (item.compareResult)
|
|
{
|
|
case ComparisonResult.Identical:
|
|
{
|
|
continue;
|
|
}
|
|
case ComparisonResult.MissingInLocalFolder:
|
|
{
|
|
// check of the upload flag was set
|
|
if ((flags & SyncFolderFlags.DownloadItems) != SyncFolderFlags.DownloadItems)
|
|
continue;
|
|
|
|
// copy remote to local or create path
|
|
|
|
// 1. get the rel path
|
|
string relPath;
|
|
if (item.remoteItem is ICloudDirectoryEntry)
|
|
relPath = GetFullCloudPath(tgtFolder, item.remoteItem, '\\');
|
|
else
|
|
relPath = GetFullCloudPath(tgtFolder, item.remoteItem.Parent, '\\');
|
|
|
|
// 2. ensure the directory exists
|
|
var tgtPath = Path.Combine(srcFolder.FullName, relPath);
|
|
if (!Directory.Exists(tgtPath))
|
|
Directory.CreateDirectory(tgtPath);
|
|
|
|
// 3. download file if needed
|
|
if (!(item.remoteItem is ICloudDirectoryEntry))
|
|
{
|
|
DownloadFile(item.remoteItem.Parent, item.remoteItem.Name, tgtPath);
|
|
}
|
|
break;
|
|
}
|
|
case ComparisonResult.MissingInRemoteFolder:
|
|
{
|
|
// check of the upload flag was set
|
|
if ((flags & SyncFolderFlags.UploadItems) != SyncFolderFlags.UploadItems)
|
|
continue;
|
|
|
|
// copy local to remote
|
|
|
|
// 1. get the rel path
|
|
string relPath;
|
|
if ((item.localItem.Attributes & FileAttributes.Directory) == FileAttributes.Directory)
|
|
relPath = item.localItem.FullName.Remove(0, srcFolder.FullName.Length);
|
|
else
|
|
relPath = Path.GetDirectoryName(item.localItem.FullName).Remove(0, srcFolder.FullName.Length);
|
|
|
|
// 2. convert delimit
|
|
relPath = relPath.Replace(Path.DirectorySeparatorChar, '/');
|
|
|
|
// 3. ensure the directory exists
|
|
ICloudDirectoryEntry realTarget;
|
|
|
|
if (relPath.Length == 0)
|
|
realTarget = tgtFolder;
|
|
else
|
|
{
|
|
if (relPath[0] == '/')
|
|
relPath = relPath.Remove(0, 1);
|
|
|
|
//check if subfolder exists, if it doesn't, create it
|
|
realTarget = GetFolder(relPath, tgtFolder) ?? CreateFolderEx(relPath, tgtFolder);
|
|
}
|
|
|
|
// 4. check target
|
|
if (realTarget == null)
|
|
{
|
|
bRet = false;
|
|
continue;
|
|
}
|
|
|
|
// 5. upload file if needed
|
|
if ((item.localItem.Attributes & FileAttributes.Directory) != FileAttributes.Directory)
|
|
{
|
|
if (UploadFile(item.localItem.FullName, realTarget) == null)
|
|
bRet = false;
|
|
}
|
|
break;
|
|
}
|
|
|
|
case ComparisonResult.SizeDifferent:
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
}
|
|
}
|
|
|
|
return bRet;
|
|
}
|
|
|
|
/// <summary>
|
|
/// This function allows to synchronize a local folder with an folder exists in the cloud storage
|
|
/// and vice versa. The local folder and the target folder has to be created before.
|
|
/// </summary>
|
|
/// <param name="srcFolder"></param>
|
|
/// <param name="tgtFolder"></param>
|
|
/// <param name="flags"></param>
|
|
/// <returns></returns>
|
|
public bool SynchronizeFolder(string srcFolder, string tgtFolder, SyncFolderFlags flags)
|
|
{
|
|
// check parameters
|
|
if (srcFolder == null || tgtFolder == null || flags == SyncFolderFlags.Empty)
|
|
return false;
|
|
|
|
// build directory info for local folder
|
|
var srcFolderInfo = new DirectoryInfo(srcFolder);
|
|
|
|
// build the target folder
|
|
var tgtFolderEntry = GetFolder(tgtFolder);
|
|
if (tgtFolderEntry == null)
|
|
return false;
|
|
|
|
// call the sync job
|
|
return SynchronizeFolder(srcFolderInfo, tgtFolderEntry, flags);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns a path to the file object
|
|
/// </summary>
|
|
/// <param name="fsentry"></param>
|
|
/// <returns></returns>
|
|
public static string GetFullCloudPath(ICloudFileSystemEntry fsentry)
|
|
{
|
|
return GetFullCloudPath(fsentry, '/');
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns a path to the file object
|
|
/// </summary>
|
|
/// <param name="fsentry">start entry</param>
|
|
/// <param name="cDelimiter">delimiter</param>
|
|
/// <returns></returns>
|
|
public static string GetFullCloudPath(ICloudFileSystemEntry fsentry, char cDelimiter)
|
|
{
|
|
// create string builder
|
|
var sb = new StringBuilder();
|
|
|
|
// add the object as self
|
|
sb.Insert(0, fsentry.Name);
|
|
|
|
// add the delimiter
|
|
sb.Insert(0, cDelimiter);
|
|
|
|
// visit every parent
|
|
var current = fsentry.Parent;
|
|
while (current != null)
|
|
{
|
|
// add the item
|
|
sb.Insert(0, current.Name);
|
|
|
|
// add the delimiter
|
|
sb.Insert(0, cDelimiter);
|
|
|
|
// go up
|
|
current = current.Parent;
|
|
}
|
|
|
|
// return result
|
|
return sb.ToString();
|
|
}
|
|
|
|
/// <summary>
|
|
///
|
|
/// </summary>
|
|
/// <param name="start"></param>
|
|
/// <param name="fsentry"></param>
|
|
/// <param name="cDelimiter"></param>
|
|
/// <returns></returns>
|
|
public static string GetFullCloudPath(ICloudDirectoryEntry start, ICloudFileSystemEntry fsentry, char cDelimiter)
|
|
{
|
|
var strfsentry = GetFullCloudPath(fsentry, cDelimiter);
|
|
var strStart = GetFullCloudPath(start, cDelimiter);
|
|
|
|
return strfsentry.Remove(0, strStart.Length);
|
|
}
|
|
}
|
|
} |