I have created a MVC WebRole Window Azure application where i upload encrypted files to Azure blob storage using SymmetricAlgorithm (Rijndael) like this
Controler>Action is
[HttpPost]
public ActionResult UploadImage_post(HttpPostedFileBase fileBase)
{
if (fileBase.ContentLength > 0)
{
// Retrieve a reference to a container
Microsoft.WindowsAzure.StorageClient.CloudBlobContainer blobContainer =
_myBlobStorageService.GetCloudBlobContainer();
Microsoft.WindowsAzure.StorageClient.CloudBlob blob =
blobContainer.GetBlobReference(fileBase.FileName);
using (BlobStream blobStream = blob.OpenWrite())
{
string encryptionKey = //somekey;
byte[] file = new byte[fileBase.ContentLength];
EncDecAlgo.EncryptBlobFile(file, blobStream, encryptionKey);
}
}
}
public void EncryptBlobFile(byte[] file, BlobStream bs, string key)
{
PasswordDeriveBytes pdb = new PasswordDeriveBytes(key,
new byte[] {0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d,
0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76});
Rijndael alg = Rijndael.Create();
alg.Key = pdb.GetBytes(32);
alg.IV = pdb.GetBytes(16);
CryptoStream cs = new CryptoStream(bs,
alg.CreateEncryptor(), CryptoStreamMode.Write);
foreach (var data in file)
{
cs.WriteByte((byte)data);
}
cs.Close();
bs.Close();
}
The above File encryption is working fine.
For Downloading code is
public ActionResult DownloadFile(string filename)
{
// Retrieve reference to a previously created container.
Microsoft.WindowsAzure.StorageClient.CloudBlobContainer blobContainer =
_myBlobStorageService.GetCloudBlobContainer();
Microsoft.WindowsAzure.StorageClient.CloudBlob blob =
blobContainer.GetBlobReference(filename);
blob.FetchAttributes();
string encryptionKey = //same key used in encryption;
using (BlobStream blobStream = blob.OpenRead())
{
EncDecAlgo.DecryptBlobFile(blobStream, encryptionKey, filename);
}
}
public static void DecryptBlobFile(BlobStream bs, string key, string filePath)
{
try
{
PasswordDeriveBytes pdb = new PasswordDeriveBytes(key,
new byte[] {0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65,
0x64, 0x76, 0x65, 0x64, 0x65, 0x76});
Rijndael alg = Rijndael.Create();
alg.Key = pdb.GetBytes(32);
alg.IV = pdb.GetBytes(16);
CryptoStream cs = new CryptoStream(bs,
alg.CreateDecryptor(), CryptoStreamMode.Read);
// Decrypt & Download Here
System.Web.HttpContext.Current.Response.AddHeader("Content-Disposition", "attachment; filename=" + Path.GetFileName(filePath));
System.Web.HttpContext.Current.Response.ContentType = "application/" + Path.GetExtension(filePath).Replace(".", "");
int data;
while ((data = cs.ReadByte()) != -1)
{
if (data != 0)
{
}
System.Web.HttpContext.Current.Response.OutputStream.WriteByte((byte)data);
System.Web.HttpContext.Current.Response.Flush();
}
cs.Close();
bs.Close();
}
catch
{
}
}
On downloading get following error
Server cannot set content type after HTTP headers have been sent.
Please suggest some solution.
This should be fairly simple, hope this is enough to get you started:
public class CloudFileResult : ActionResult
{
private string m_FileName;
private CloudBlobContainer m_Container;
public CloudFileResult(string imageName, CloudBlobContainer container)
{
if (string.IsNullOrEmpty(imageName))
{
throw new ArgumentNullException("imageName");
}
if (container == null)
{
throw new ArgumentNullException("container");
}
m_FileName = imageName;
m_Container = container;
}
public override void ExecuteResult(ControllerContext context)
{
context.HttpContext.Response.Clear();
var blockBlob = m_Container.GetBlockBlobReference(m_FileName);
blockBlob.FetchAttributes();
context.HttpContext.Response.ContentType = blockBlob.Metadata["ContentType"];
const string key = "my secret";
using (var pdb = new Rfc2898DeriveBytes(key, new byte[] { 0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76 }))
{
using (var alg = RijndaelManaged.Create())
{
alg.Key = pdb.GetBytes(32);
alg.IV = pdb.GetBytes(16);
using (var stream = new CryptoStream(context.HttpContext.Response.OutputStream, alg.CreateDecryptor(), CryptoStreamMode.Write))
{
blockBlob.DownloadToStream(stream);
}
}
}
}
}
static void UploadFileToCloud(CloudBlobContainer container, HttpPostedFileBase file)
{
const string key = "my secret";
using (var pdb = new Rfc2898DeriveBytes(key, new byte[] { 0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76 }))
{
using (var alg = RijndaelManaged.Create())
{
alg.Key = pdb.GetBytes(32);
alg.IV = pdb.GetBytes(16);
var blockBlob = container.GetBlockBlobReference(file.FileName);
using (var stream = new CryptoStream(file.InputStream, alg.CreateEncryptor(), CryptoStreamMode.Read))
{
blockBlob.UploadFromStream(stream);
}
blockBlob.Metadata.Add("ContentType", file.ContentType);
blockBlob.SetMetadata();
}
}
}
static CloudBlobContainer GetContainer()
{
string connection = "DefaultEndpointsProtocol=http;AccountName=AzureAccount;AccountKey=AzureAccountKey;";
var account = CloudStorageAccount.Parse(connection);
var client = account.CreateCloudBlobClient();
var container = client.GetContainerReference("container");
return container;
}
As for download you can simple use:
[HttpGet]
public ActionResult Index(string fileName)
{
if (!string.IsNullOrEmpty(fileName))
{
return new CloudFileResult(fileName, GetContainer());
}
return View();
}
Pointers: