Download Zip file from azure Storage c# - azure

I am looping through the file names from my database and the same file i have in azure storage. I am zipping those n number of files and download from azure storage. I saves the zipped file to my local storage. When i extract and want to see a file, it say damaged/corrupt.
public ActionResult Download(string productid, string YearActiveid)
{
HomePageModel homepagemodel = new HomePageModel();
homepagemodel.ProdHeaderDetail = GetProductHeaderDetail(productid, YearActiveid);
homepagemodel.PriorYearsActive = GetPriorYearActive(productid, YearActiveid);
CloudStorageAccount cloudStorageAccount = CloudStorageAccount.Parse("DefaultEndpointsProtocol=https;AccountName=<name>;AccountKey=<key>;EndpointSuffix=core.windows.net");
CloudBlobClient cloudBlobClient = cloudStorageAccount.CreateCloudBlobClient();
CloudBlobContainer cloudBlobContainer = cloudBlobClient.GetContainerReference("product");
var blobFileNames = new string[] { "file1.png", "file2.png", "file3.png", "file4.png" };
var outputMemStream = new MemoryStream();
var zipOutputStream = new ZipOutputStream(outputMemStream);
foreach (var ProdHeaderDetail in homepagemodel.ProdHeaderDetail)
{
zipOutputStream.SetLevel(5);
var blob = cloudBlobContainer.GetBlockBlobReference(ProdHeaderDetail.FileName);
var entry = new ZipEntry(ProdHeaderDetail.FileName);
zipOutputStream.PutNextEntry(entry);
blob.DownloadToStreamAsync(zipOutputStream);
}
zipOutputStream.Finish();
//zipOutputStream.Close();
//zipOutputStream.CloseEntry();
zipOutputStream.IsStreamOwner = false;
outputMemStream.Position = 0;
return File(outputMemStream, "application/zip", "filename.zip");
}

I resolved the issue by adding async and wait
public async Task Download(string productid, string YearActiveid)
await blob.DownloadToStreamAsync(zipOutputStream);

Related

Migrate from Azure to SharePoint using Migration API - "Must specify IV in Manifest or blob metadata'"

I am trying to use the Migration API with C# to migrate from the default free Azure Cloud (given to all sharepoint accounts) to SharePoint.
I can successfully generate a cloud container, and upload files, but the migration fails. Here is my code:
private void MigrateToAzureThenSharePoint()
{
//Provision The default Azure Containers and Migation Queue
var migrationContainers = destinationCtx.Site.ProvisionMigrationContainers();
var migrationQueue = destinationCtx.Site.ProvisionMigrationQueue();
destinationCtx.ExecuteQuery();
var containerInfoList = migrationContainers.Value;
var dataContainerUri = containerInfoList.DataContainerUri;
var metadataContainerUri = containerInfoList.MetadataContainerUri;
var queueInfo = migrationQueue.Value;
//Instansiate Cloud Queue
var cloudQueue = new CloudQueue(new Uri(queueInfo.JobQueueUri));
//Instansiate CloudBlobContainer
CloudBlobContainer dataContainer = new CloudBlobContainer(new Uri(dataContainerUri));
CloudBlobContainer manifestContainer = new CloudBlobContainer(new Uri(metadataContainerUri));
//Test files to upload
var testfiles = new[]
{
new SourceFile
{
Filename = "test.txt",
LastModified = DateTime.Now,
Contents = Encoding.UTF8.GetBytes("Hi, this is a test text-file"),
Title = "Title of file 1"
},
new SourceFile
{
Filename = "test2.txt",
LastModified = DateTime.Now.AddDays(-1),
Contents = Encoding.UTF8.GetBytes("Tesfile2"),
Title = "Second title"
}
};
//Upload Test Files to Cloud
foreach (var testfile in testfiles)
{
var blobReference = dataContainer.GetBlockBlobReference(testfile.Filename);
blobReference.UploadFromByteArray(testfile.Contents, 0, testfile.Contents.Length, null);
blobReference.CreateSnapshot();
}
var manifestPackage = new ManifestPackage(destOrganisationList.Id,
destinationCtx.Web.Id,
destinationCtx.Web.Title,
destOrganisationList.Title,
#"\",
destOrganisationList.RootFolder.UniqueId,
destOrganisationList.RootFolder.ParentFolder.UniqueId
);
//Create XML Files for Azure Migration (An easier way here would be great? I manualy write them)
var filesInManifestPackage = manifestPackage.GetManifestPackageFiles(testfiles);
//Uploaded manually created XML files
foreach (var migrationPackageFile in filesInManifestPackage)
{
var blobReference = manifestContainer.GetBlockBlobReference(migrationPackageFile.Filename);
blobReference.UploadFromByteArray(migrationPackageFile.Contents, 0, migrationPackageFile.Contents.Length, null);
blobReference.CreateSnapshot();
}
//Start Migration
var result = destinationCtx.Site.CreateMigrationJobEncrypted(destinationCtx.Web.Id,
containerInfoList.DataContainerUri,
containerInfoList.MetadataContainerUri,
queueInfo.JobQueueUri,
new EncryptionOption()
{
AES256CBCKey = containerInfoList.EncryptionKey
});
destinationCtx.ExecuteQuery();
//Check for messags
while (true) {
var msg = cloudQueue.GetMessage();
if (msg == null)
{
Task.Delay(TimeSpan.FromSeconds(1));
continue;
}
var message = JsonConvert.DeserializeObject<EncryptedMessage>(msg.AsString);
cloudQueue.DeleteMessage(msg);
//Decode encrypted message
var decoded = JsonConvert.DeserializeObject<UpdateMessage>(Decrypt(message.Content, containerInfoList.EncryptionKey, message.IV));
//Error
}
}
There are a few errors, but they all are similar to this:
"Unable to download SystemData.xml with exception 'Must specify IV in
Manifest or blob metadata'"
I believe I may have to encrypt the files when I upload from this method:
blobReference.UploadFromByteArray
There is an option:
var blobRequestOptions = new BlobRequestOptions();
blobRequestOptions.EncryptionPolicy =
But I don't know how to instantiate the encryption policy (and I may be going down a rabbit hole)
Any help would be greatly appreciated, as documentation online is shocking minimal.

How can I dynamically create Ziparchive in Azure

I have multiple files in my Azure storage account say its Master container, I have created a dynamic container which will have the required files copied from Master Container, and those coped files needed to be zipped inside that created container. See below code, where in I have created the zip archive. Also the zip archive is getting created, but when I download manually and see the files, it seems corrupted (for ex. the actual size of the individual files are more than 1Mb but the files which I get after download seems 22Kb), and File formats would be .ipt, .iam (Autodesk Inventor Files)
CloudBlobContainer destContainer = blobClient.GetContainerReference(AzureContainer);
bool isCreated = destContainer.CreateIfNotExists();
var zipblob = destContainer.GetBlockBlobReference("inputAssembly.zip");
using (var stream = await zipblob.OpenWriteAsync())
using (var zip = new ZipArchive(stream, ZipArchiveMode.Create))
{
foreach (var fileName in inputfile)
{
using (var fileStream = new MemoryStream())
{
if (destContainer.GetBlockBlobReference(fileName).Exists())
{
destContainer.GetBlockBlobReference(fileName).DownloadToStream(fileStream);
}
var newZip = new ZipArchive(fileStream, ZipArchiveMode.Create);
var entry = newZip.CreateEntry(fileName, CompressionLevel.NoCompression);
using (var innerFile = entry.Open())
{
fileStream.CopyTo(innerFile);
}
fileStream.Close();
}
}
}
CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
CloudBlobContainer container = blobClient.GetContainerReference(fixedpartContainer);
CloudBlobContainer destContainer1 = blobClient.GetContainerReference(AzureContainer);
bool isCreated = destContainer1.CreateIfNotExists();
var zipblob = destContainer1.GetBlockBlobReference("inputAssembly.zip");
using (var stream = await zipblob.OpenWriteAsync())
{
using (var zipArchive = new ZipArchive(stream, ZipArchiveMode.Create))
{
foreach (var blobName in blobFileNames)
{
var blob = destContainer.GetBlockBlobClient(blobName);
var zipEntry = zipArchive.CreateEntry(blobName);
using var zipStream = zipEntry.Open();
using var fileStream = new MemoryStream();
await blob.DownloadToAsync(fileStream);
await zipStream.WriteAsync(fileStream.ToArray());
AssemblyCreated = true;
}
}
}

zip all files in azure blob container

I am trying to use azure function to zip all files inside a blob container using System.IO.Compression.
I could list all files inside the container using the below CloudBlob code
CloudStorageAccount storageAccount = CloudStorageAccount.Parse (storageConn);
CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
CloudBlobContainer container = blobClient.GetContainerReference("<container>");
BlobContinuationToken blobToken = null;
var blobs = await container.ListBlobsSegmentedAsync(blobToken);
var fileList = new List<string>();
var blobpath1 = #"https://<pathtocontainer>/test.zip";
foreach (var blbitem in blobs.Results)
{
if (blbitem is CloudBlockBlob)
{
var blobFileName = blbitem.Uri.Segments.Last().Replace("%20", " ");
var blobFilePath = blbitem.Uri.AbsolutePath.Replace(blbitem.Container.Uri.AbsolutePath + "/", "").Replace("%20", " ");
var blobPath = blobFilePath.Replace("/" + blobFileName, "");
log.LogInformation("blob path : " + blbitem.Uri.ToString());
fileList.Add(blbitem.Uri.ToString());
string rootpath = #"D:\home\site\wwwroot\ZipandSendFile\temp\";
string path = rootpath + blobPath;
log.LogInformation("saving in " + path);
//Add to zip
/*
CloudBlobContainer container = cloudBlobClient.GetContainerReference("<container>");
CloudBlockBlob blob = container.GetBlockBlobReference(blobName);
using (FileStream fs = new FileStream(rootpath, FileMode.Create))
{
blob. DownloadToStream(fs);
}
*/
}
}
</code>
After getting each file details inside the blob , I am trying to add them into zip archive
using the below System.IO.Compression package
My attempt to download file
<code>
public static void AddFilesToZip(string zipPath, string[] files,ILogger log)
{
if (files == null || files.Length == 0)
{
return;
}
log.LogInformation("Executing add files to zip");
log.LogInformation(zipPath);
using (var zipArchive = ZipFile.Open(zipPath, ZipArchiveMode.Update))
{
log.LogInformation("in Zip archive");
foreach (var file in files)
{
var fileInfo = new FileInfo(file);
log.LogInformation(fileInfo.FullName);
zipArchive.CreateEntryFromFile(fileInfo.FullName, fileInfo.Name);
}
}
}
</code>
But I am getting access denied. Any pointers on this ?
Resolved issue by logging into kudo cmdshell and cd into directory and change file attribute
with attrib +A .

Insert Image into Dynamically create PDF in AZURE BLOB Storage

I created one dynamic PDF in AZURE BLOB Storage. All content is write perfectly. Now I want to add Image at top of the PDF content from one of blob storage. For create PDF my code is as below :
//Parse the connection string and return a reference to the storage account.
CloudStorageAccount storageAccount = CloudStorageAccount.Parse(CloudConfigurationManager.GetSetting("connectionstring"));
//Create the blob client object.
CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
//Get a reference to a container to use for the sample code, and create it if it does not exist.
CloudBlobContainer container = blobClient.GetContainerReference("containername");
container.CreateIfNotExists();
MemoryStream ms1 = new MemoryStream();
ms1.Position = 0;
using (ms1)
{
var doc1 = new iTextSharp.text.Document();
PdfWriter writer = PdfWriter.GetInstance(doc1, ms1);
doc1.Open();
doc1.Add(new Paragraph("itextSharp DLL"));
doc1.Close();
var byteArray = ms1.ToArray();
var blobName = "testingCREATEPDF.pdf";
var blob = container.GetBlockBlobReference(blobName);
blob.Properties.ContentType = "application/pdf";
blob.UploadFromByteArray(byteArray, 0, byteArray.Length);
}
Please let me know how to add image at top of PDF from azure blob.
Try the code below. Basically the trick is to read the blob's data as a stream and create an iTextSharp.text.Image from that stream. Once you have that object, you can insert it in your PDF document.
private static void CreatePdf()
{
var account = new CloudStorageAccount(new StorageCredentials(accountName, accountKey), true);
var blobClient = account.CreateCloudBlobClient();
var container = blobClient.GetContainerReference("pdftest");
container.CreateIfNotExists();
var imagesContainer = blobClient.GetContainerReference("images");
var imageName = "Storage-blob.png";
using (MemoryStream ms = new MemoryStream())
{
var doc = new iTextSharp.text.Document();
PdfWriter writer = PdfWriter.GetInstance(doc, ms);
doc.Open();
doc.Add(new Paragraph("Hello World"));
var imageBlockBlob = imagesContainer.GetBlockBlobReference(imageName);
using (var stream = new MemoryStream())
{
imageBlockBlob.DownloadToStream(stream);//Read blob contents in stream.
stream.Position = 0;//Reset the stream's position to top.
Image img = Image.GetInstance(stream);//Create am instance of iTextSharp.text.image.
doc.Add(img);//Add that image to the document.
}
doc.Close();
var byteArray = ms.ToArray();
var blobName = (DateTime.MaxValue.Ticks - DateTime.Now.Ticks).ToString() + ".pdf";
var blob = container.GetBlockBlobReference(blobName);
blob.Properties.ContentType = "application/pdf";
blob.UploadFromByteArray(byteArray, 0, byteArray.Length);
}
}

How to list blobs from virtual directory without prefix?

I have the following list of blobs:
VirtualDirectroy1/VirtualSubDirectory1/Blob1
VirtualDirectroy2/VirtualSubDirectory2/Blob2
VirtualDirectroy3/VirtualSubDirectory3/Blob3
I need to list Blob1, Blob2 and Blob3, so that when accessing the CloudBlockBlob.Name property it returns just Blob1, Blob2 or Blob 3 WITHOUT prefix of virtual directories.
How can I archive this?
Best Wishes, Oleg
If you are using the Azure storage .Net client library (I am using version 3.0.3 in which these methods/overloads are available), you could do something this:
var container = GetBlobContainer();
foreach (var blobItem in container.ListBlobs(useFlatBlobListing: true))
{
Console.WriteLine(blob.Parent.Uri.MakeRelativeUri(blob.Uri));
}
I found you can do this:
var storageAccountConnectionString = "...";
var storageAccount = CloudStorageAccount.Parse(storageAccountConnectionString);
var cloudBlobClient = storageAccount.CreateCloudBlobClient();
var cloudBlobContainer = cloudBlobClient.GetContainerReference("containerName");
foreach (var blob in cloudBlobContainer.ListBlobs())
{
Console.WriteLine(blob.Uri.Segments.Last());
}
class Program
{
const string _conStr = "storage connection string";
const string _container = "container name";
static void Main(string[] args)
{
var names = new Program().GetBlobNames();
Console.ReadKey();
}
private List<string> GetBlobNames()
{
CloudStorageAccount acc = CloudStorageAccount.Parse(_conStr);
CloudBlobClient blobClient = acc.CreateCloudBlobClient();
CloudBlobContainer cntnr = blobClient.GetContainerReference(_container);
List<IListBlobItem> blobList = cntnr.ListBlobs("").ToList();
List<string> flatList = new List<string>();
List<IListBlobItem> blobItems = new List<IListBlobItem>();
foreach (IListBlobItem blobItem in blobList)
{
//If it is cloudblob directory
if (blobItem.GetType() == typeof(CloudBlobDirectory))
{
CloudBlobDirectory dir = blobItem as CloudBlobDirectory;
GetFilesInDirectory(dir, blobItems);
}
}
return blobItems.Select(b => b.Parent.Uri.MakeRelativeUri(b.Uri).ToString()).ToList();
}
private void GetFilesInDirectory(CloudBlobDirectory directory, List<IListBlobItem> fileList)
{
foreach (var blobItem in directory.ListBlobs())
{
if (blobItem.GetType() == typeof(CloudBlockBlob))
{
CloudBlockBlob blob = (CloudBlockBlob)blobItem;
fileList.Add(blob);
}
else if (blobItem.GetType() == typeof(CloudPageBlob))
{
CloudPageBlob blob = (CloudPageBlob)blobItem;
fileList.Add(blob);
}
else if (blobItem.GetType() == typeof(CloudBlobDirectory))
{
//Fetch recursively all the blobs
CloudBlobDirectory blob = (CloudBlobDirectory)blobItem;
GetFilesInDirectory(blob, fileList);
}
}
}
}

Resources