Get Azure Batch ResourceFile from existing file in Azure Blob Container - azure-blob-storage

I am following this tutorial to do my first steps with Azure Batch
https://github.com/Azure-Samples/batch-dotnet-ffmpeg-tutorial/blob/master/BatchDotnetTutorialFfmpeg/Program.cs
There is one method to upload files to a container and to get back a ResourceFile for further processing.
private static ResourceFile UploadFileToContainer(CloudBlobClient blobClient, string containerName, string filePath)
{
Console.WriteLine("Uploading file {0} to container [{1}]...", filePath, containerName);
string blobName = Path.GetFileName(filePath);
filePath = Path.Combine(Environment.CurrentDirectory, filePath);
CloudBlobContainer container = blobClient.GetContainerReference(containerName);
CloudBlockBlob blobData = container.GetBlockBlobReference(blobName);
blobData.UploadFromFileAsync(filePath).Wait();
// Set the expiry time and permissions for the blob shared access signature.
// In this case, no start time is specified, so the shared access signature
// becomes valid immediately
SharedAccessBlobPolicy sasConstraints = new SharedAccessBlobPolicy
{
SharedAccessExpiryTime = DateTime.UtcNow.AddHours(2),
Permissions = SharedAccessBlobPermissions.Read
};
// Construct the SAS URL for blob
string sasBlobToken = blobData.GetSharedAccessSignature(sasConstraints);
string blobSasUri = String.Format("{0}{1}", blobData.Uri, sasBlobToken);
return ResourceFile.FromUrl(blobSasUri, filePath);
}
This works fine as long as you want to upload your files again and again. For some reason my upload broke down and I did not get the ResourceFile Object.
So how can I get a ResourceFile Object from an already uploaded file to an existing container?
Regards
Michael

Related

Xamarin Uploading sqllite file to Azure Blob storage, sqlite .db3 file is empty on Blob storage

I'm trying to upload the local database of the app build in Xamarin forms iOS. There is data in the local database and the app can see all the table and data just fine.
I want to investigate the database, so I upload it to an Azure Blob storage.
The code look like this:
public class BlobStorageService
{
readonly static CloudStorageAccount cloudStorageAccount = CloudStorageAccount.Parse(Constants.blogStorageConnectionString);
readonly static CloudBlobClient blobClient = cloudStorageAccount.CreateCloudBlobClient();
public static async Task UploadFileToBlobStorage(string filePath)
{
if (!File.Exists(filePath))
return;
var fileName = Path.GetFileName(filePath);
CloudBlobContainer container = blobClient.GetContainerReference("sqllitefiles");
await container.CreateIfNotExistsAsync();
BlobContainerPermissions permissions = await container.GetPermissionsAsync();
permissions.PublicAccess = BlobContainerPublicAccessType.Container; //TODO: disable this later.
await container.SetPermissionsAsync(permissions);
CloudBlockBlob blockBlob = container.GetBlockBlobReference(fileName);
await blockBlob.UploadFromFileAsync(filePath);
}
}
And the filePath is :
public static readonly string DatabasePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "CaseNotesSQLite.db3");
Database file is uploaded successfully, however, the file is only 4KB and when I open the database file using SQLLite Browser, there is no data and no table structure at all.
Anyone know why ?

Spring MVC Resources not refreshing

I'm working on an image manager system for my Spring MVC project, with the basic functions of displaying the gallery of all images stored in the local image folder, deleting images and uploading new images.
I would like that, once a new image is uploaded, the page reloads the images gallery, including the image just added. What it happens in fact is that the new image is correctly saved on the HD, but it doesn't automatically show up in the resources/img folder in the Java project; therefore, once the page is reloaded, the new image is not there. Only when I manually refresh the project, the new image appears in the resources/img folder.
The odd thing is, I don't have the same problem with the delete method: once an image is deleted, it disappears from the HD AND the resources/img folder, and the page reloads the gallery without showing the image just deleted.
Any idea where the problem could be?
Here is my controller
#Controller
public class imagesManagerController {
// READ ALL FILES FROM IMG FOLDER
#RequestMapping(value = "/imagesManager", method = RequestMethod.GET)
public ModelAndView readImages
(#RequestParam(value = "error", required = false) String error) {
// create model and link it to jsp imagesManager
ModelAndView model = new ModelAndView("imagesManager");
// return content from images folder and add it to model
File imgsPath = new File("C:/Users/Alessandro/workspace/SpringMVCBlog/WebContent/resources/img");
String[] imgsNames = imgsPath.list();
model.addObject("imgsNames", imgsNames);
//if upload fails, display error message
if (error != null) {
model.addObject("error",
"Please select a file to upload");
}
return model;
}
//UPLOAD FILE TO HD
#RequestMapping(value = "/imagesManager/upload", method = RequestMethod.POST)
public String handleFileUpload (#RequestParam("file") MultipartFile file) {
//get img name
String imgName = file.getOriginalFilename();
System.out.println(imgName);
//create file path
String folder = "C:/Users/Alessandro/workspace/SpringMVCBlog/WebContent/resources/img/";
File path = new File (folder+imgName);
System.out.println(path);
if (!file.isEmpty()) {
try {
//get bytes array from file
byte[] bytes = file.getBytes();
//create output stream
BufferedOutputStream stream = new BufferedOutputStream(
new FileOutputStream(path));
//write img content on path
stream.write(bytes);
//close stream
stream.close();
//if upload is successful, reload page
return "redirect:/imagesManager";
} catch (Exception e) {
return "You failed to upload " + imgName + " => " + e.getMessage();
}
} else {
return "redirect:/imagesManager?error";
}
}
// DELETE FILE FROM HD
#RequestMapping(value = "/imagesManager/delete", method = RequestMethod.POST)
public String deleteFile(#RequestParam (value="imgName") String imgName) {
//create file path to be deleted
String folder = "C:/Users/Alessandro/workspace/SpringMVCBlog/WebContent/resources/img/";
File path = new File (folder+imgName);
// delete file
if (path.delete()) {
//if delete is successful, reload page
return "redirect:/imagesManager";
} else {
return "Delete operation failed";
}
}
}
The problem is in the path:
WebContent/resources/img
It is refreshing probably due to IDE server auto-deployment. Test with %TEMP% path and check.
1) You should not save uploaded files to the application server file system.
2) You should not save uploaded files to the application folder as it is part of the deployment. It will only be deployed once and that folder is only for the application files.
Instead, use the cloud or a dedicated file system.

Upload to Azure Blob from Xamarin.Forms PCL

I'm trying to upload an image's stream to Azure Blob from a Xamarin.Forms PCL app using WindowsAzure.Storage 7.0.2-preview. For some reason, the StorageCredentials doesn't recognize the AccountName of the SAS token.
var credentials = new StorageCredentials("https://<ACCOUNT-NAME>.blob.core.windows.net/...");
CloudStorageAccount Account = new CloudStorageAccount(credentials, true);
And then uploading it like this:
public async Task<string> WriteFile(string containerName, string fileName, System.IO.Stream stream, string contentType = "")
{
var container = GetBlobClient().GetContainerReference(containerName);
var fileBase = container.GetBlockBlobReference(fileName);
await fileBase.UploadFromStreamAsync(stream);
if (!string.IsNullOrEmpty(contentType))
{
fileBase.Properties.ContentType = contentType;
await fileBase.SetPropertiesAsync();
}
return fileBase.Uri.ToString();
}
How can I resolve my problem? Is there a better solution of uploading to Azure Storage?
Thank you!
The StorageCredentials constructor that takes in a SAS token expects just the query part of the SAS token, not the full URI string. If you have the full URI to a resource, including the SAS token, the most common thing to do is to use the constructor for that object directly. For example, if you have the URI:
string myBlobUri = #"https://myaccount.blob.core.windows.net/sascontainer/sasblob.txt?sv=2015-04-05&st=2015-04-29T22%3A18%3A26Z&se=2015-04-30T02%3A23%3A26Z&sr=b&sp=rw&sip=168.1.5.60-168.1.5.70&spr=https&sig=Z%2FRHIX5Xcg0Mq2rqI3OlWTjEg2tYkboXr1P9ZUXDtkk%3D";
you can just create a blob object as such:
CloudBlockBlob fileBase = new CloudBlockBlob(new Uri(myBlobUri));
If you do want to use the StorageCredentials and CloudStorageAccount classes for some reason (maybe you have an AccountSAS, for example), here is one way to make that work:
string sasToken = #"sv=2015-04-05&st=2015-04-29T22%3A18%3A26Z&se=2015-04-30T02%3A23%3A26Z&sr=b&sp=rw&sip=168.1.5.60-168.1.5.70&spr=https&sig=Z%2FRHIX5Xcg0Mq2rqI3OlWTjEg2tYkboXr1P9ZUXDtkk%3D";
StorageCredentials credentials = new StorageCredentials(sasToken);
CloudStorageAccount account = new CloudStorageAccount(credentials, "myaccount", "core.windows.net", true)

File Download from Azure Blob

Below code is for donwnloading file from azure blob. I have problem with .docx,.xlsx files and that too after deployment only, mean in local machine it is working fine.
The problem is after downloading .xlsx or .docx, when i open that file showing file corrupted popup.
public void DownloadBlob(string blobName)
{
//You have to get values for below items from azure
string accountName = "MyAccName";
string accountPrimaryKey = "MyKey";
string blobContainer = "ContainerName";
CloudStorageAccount account = new CloudStorageAccount(new StorageCredentialsAccountAndKey(accountName, accountPrimaryKey), false);
CloudBlobClient blobClient = account.CreateCloudBlobClient();
CloudBlobContainer container = blobClient.GetContainerReference(blobContainer);
CloudBlob blob = container.GetBlobReference(blobName);
MemoryStream memStream = new MemoryStream();
blob.DownloadToStream(memStream);
Response.ContentType = blob.Properties.ContentType;
Response.AddHeader("Content-Disposition", "Attachment; filename=" + blobName.ToString());
Response.AddHeader("Content-Length", (blob.Properties.Length - 1).ToString());
Response.BinaryWrite(memStream.ToArray());
Response.End();
}
I am sure you have issue with your code as As Steve suggested you are setting length incorrectly.
I worked on similar issue sometime last year and documented the solution in my blog as below:
http://blogs.msdn.com/b/avkashchauhan/archive/2011/04/05/downloading-word-and-excel-files-from-windows-azure-storage-in-a-asp-net-web-role.aspx

Windows Azure: Creation of a file on cloud blob container

I am writing a program that will be executing on the cloud. The program will generate an output that should be written on to a file and the file should be saved on the blob container.
I don't have a idea of how to do that
Will this code
FileStream fs = new FileStream(file, FileMode.Create);
StreamWriter sw = new StreamWriter(fs);
generate a file named "file" on the cloud...
Oh.. then how to store the content to the blob..
Are you attempting to upload a Page blob or a Block blob? Usually block blobs are what are required, unless you are going to create a VM from the blob image, then a page blob is needed.
Something like this works however. This snippet taken from the most excellent Blob Transfer Utility Check it out for all your upload and download blob needs. (Just change the type from Block To Page if you need a VHD)
public void UploadBlobAsync(ICloudBlob blob, string LocalFile)
{
// The class currently stores state in class level variables so calling UploadBlobAsync or DownloadBlobAsync a second time will cause problems.
// A better long term solution would be to better encapsulate the state, but the current solution works for the needs of my primary client.
// Throw an exception if UploadBlobAsync or DownloadBlobAsync has already been called.
lock (WorkingLock)
{
if (!Working)
Working = true;
else
throw new Exception("BlobTransfer already initiated. Create new BlobTransfer object to initiate a new file transfer.");
}
// Attempt to open the file first so that we throw an exception before getting into the async work
using (FileStream fstemp = new FileStream(LocalFile, FileMode.Open, FileAccess.Read)) { }
// Create an async op in order to raise the events back to the client on the correct thread.
asyncOp = AsyncOperationManager.CreateOperation(blob);
TransferType = TransferTypeEnum.Upload;
m_Blob = blob;
m_FileName = LocalFile;
var file = new FileInfo(m_FileName);
long fileSize = file.Length;
FileStream fs = new FileStream(m_FileName, FileMode.Open, FileAccess.Read, FileShare.Read);
ProgressStream pstream = new ProgressStream(fs);
pstream.ProgressChanged += pstream_ProgressChanged;
pstream.SetLength(fileSize);
m_Blob.ServiceClient.ParallelOperationThreadCount = 10;
asyncresult = m_Blob.BeginUploadFromStream(pstream, BlobTransferCompletedCallback, new BlobTransferAsyncState(m_Blob, pstream));
}

Resources