Archive Browser
Download AzureContainerEcho.zip version 1.0.0.0, last updated 08/09/2013 (341.35 KB)
Download- md5: 08cb1fda4e8e679d8fec0608417e3910
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using Cyotek.TaskScheduler;
using Microsoft.WindowsAzure.Storage;
using Microsoft.WindowsAzure.Storage.Auth;
using Microsoft.WindowsAzure.Storage.Blob;
namespace Cyotek.AzureContainerEcho
{
public class EchoScheduledTask : ScheduledTask
{
#region Constructors
public EchoScheduledTask()
{
this.RepeatingInterval = TimeSpan.FromMinutes(15);
}
#endregion
#region Overridden Properties
public override bool IsRepeating
{
get { return true; }
}
#endregion
#region Overridden Members
protected override void ExecuteJob()
{
EchoScheduledTaskOptions options;
StorageCredentials credentials;
CloudStorageAccount account;
CloudBlobClient client;
CloudBlobContainer container;
IList<ICloudBlob> pendingRemote;
IDictionary<string, ICloudBlob> remoteItems;
options = (EchoScheduledTaskOptions)this.Data["options"];
credentials = new StorageCredentials(options.AccountName, options.AccountKey);
account = new CloudStorageAccount(credentials, true);
client = account.CreateCloudBlobClient();
container = client.GetContainerReference(options.ContainerName);
Debug.Print("Running task '{0}'", this.Name);
// create the container if it doesn't already exist
container.CreateIfNotExists();
// get all the remote items first so we don't have to query them twice
remoteItems = new Dictionary<string, ICloudBlob>(StringComparer.InvariantCultureIgnoreCase);
foreach (ICloudBlob blob in container.ListBlobs())
remoteItems.Add(blob.Name, blob);
// download
pendingRemote = this.GetMissingOrChangedRemoteBlobs(remoteItems, options.LocalPath);
if (pendingRemote.Any() && !this.IsCancelPending)
this.DownloadPendingBlobs(pendingRemote, options);
// upload
if (options.AllowUploads && !this.IsCancelPending)
{
IList<string> pendingLocal;
pendingLocal = this.GetMissingOrChangedLocalBlobs(remoteItems, options.LocalPath);
if (pendingLocal.Any() && !this.IsCancelPending)
this.UploadPendingBlobs(pendingLocal, container);
}
}
#endregion
#region Members
private void DownloadPendingBlobs(IEnumerable<ICloudBlob> pendingBlobs, EchoScheduledTaskOptions options)
{
foreach (CloudBlockBlob fileBlob in pendingBlobs)
{
string localFileName;
Debug.Print("Downloading '{0}'", fileBlob.Name);
localFileName = Path.Combine(options.LocalPath, fileBlob.Name);
using (FileStream stream = File.OpenWrite(localFileName))
fileBlob.DownloadToStream(stream);
if (fileBlob.Properties.LastModified.HasValue)
File.SetLastWriteTime(localFileName, fileBlob.Properties.LastModified.Value.UtcDateTime);
if (this.IsCancelPending)
break;
}
}
private Guid GetBlobHash(ICloudBlob fileBlob)
{
return new Guid(Convert.FromBase64String(fileBlob.Properties.ContentMD5));
}
private Guid GetMd5HashFromFile(string fileName)
{
byte[] hash;
using (FileStream file = new FileStream(fileName, FileMode.Open, FileAccess.Read))
{
MD5 md5 = new MD5CryptoServiceProvider();
hash = md5.ComputeHash(file);
}
return new Guid(hash);
}
private IList<string> GetMissingOrChangedLocalBlobs(IDictionary<string, ICloudBlob> remoteItems, string localPath)
{
IList<string> results;
results = new List<string>();
foreach (string fileName in Directory.GetFiles(localPath))
{
ICloudBlob fileBlob;
remoteItems.TryGetValue(Path.GetFileName(fileName), out fileBlob);
if (fileBlob != null && string.IsNullOrEmpty(fileBlob.Properties.ContentMD5))
fileBlob.FetchAttributes();
if (fileBlob == null || string.IsNullOrEmpty(fileBlob.Properties.ContentMD5) || this.GetMd5HashFromFile(fileName) != this.GetBlobHash(fileBlob))
{
results.Add(fileName);
if (this.IsCancelPending)
break;
}
}
Debug.Print("Found {0} missing or changed local files.", results.Count());
return results;
}
private IList<ICloudBlob> GetMissingOrChangedRemoteBlobs(IEnumerable<KeyValuePair<string, ICloudBlob>> remoteItems, string localPath)
{
IList<ICloudBlob> results;
results = new List<ICloudBlob>();
foreach (KeyValuePair<string, ICloudBlob> pair in remoteItems)
{
string localFileName;
Guid remoteHash;
ICloudBlob fileBlob;
fileBlob = pair.Value;
localFileName = Path.Combine(localPath, fileBlob.Name);
remoteHash = !string.IsNullOrEmpty(fileBlob.Properties.ContentMD5) ? this.GetBlobHash(fileBlob) : Guid.Empty;
if (!File.Exists(localFileName) || remoteHash == Guid.Empty || remoteHash != this.GetMd5HashFromFile(localFileName))
results.Add(fileBlob);
if (this.IsCancelPending)
break;
}
Debug.Print("Found {0} missing or changed remote blobs.", results.Count());
return results;
}
private void UploadPendingBlobs(IEnumerable<string> fileNames, CloudBlobContainer container)
{
foreach (string fileName in fileNames)
{
FileInfo fileInfo;
CloudBlockBlob fileBlob;
string mimeType;
fileInfo = new FileInfo(fileName);
fileBlob = container.GetBlockBlobReference(fileInfo.Name);
Debug.Print("Uploading '{0}'", fileBlob.Name);
// upload the core data
using (FileStream stream = File.OpenRead(fileInfo.FullName))
fileBlob.UploadFromStream(stream);
// update the mimetype, if one was available, otherwise just leave it as is
mimeType = MimeHelpers.GetMimeTypeFromExtension(fileInfo.Extension);
if (!string.IsNullOrEmpty(mimeType))
{
fileBlob.FetchAttributes();
fileBlob.Properties.ContentType = mimeType;
fileBlob.SetProperties();
}
// check to see if something has requested the task be cancelled and break out if so
if (this.IsCancelPending)
break;
}
}
#endregion
}
}
Donate
This software may be used free of charge, but as with all free software there are costs involved to develop and maintain.
If this site or its services have saved you time, please consider a donation to help with running costs and timely updates.
Donate