The specified blob does not exist - Download Azure Storage File From Android - azure

I know there are similar questions like this one but none of them worked for me. I am trying to download a file from Azure storage. But I am getting an error and the error message is The specified blob does not exist. But the blob does exist and my connection string is also valid. I am sharing my code below.
It would be helpful if someone can help me out.
Code:
public void downloadFile(ShowContentInfo showContentInfo){
ExecutorService executor = Executors.newSingleThreadExecutor();
Handler handler = new Handler(Looper.getMainLooper());
executor.execute(() ->{
CloudStorageAccount storageAccount = null;
try {
String dir = "/storage/emulated/0/Download/LmsContents/";
if (!dt.file.folderExists(dir)) {
dt.file.createFolder(dir);
}
storageAccount = CloudStorageAccount.parse(CONNECTION_STRING);
CloudBlobClient blobClient = storageAccount.createCloudBlobClient();
CloudBlobContainer container = blobClient.getContainerReference("containerName");
CloudBlockBlob blockBlob = container.getBlockBlobReference("rblobName");
File file = new File("/storage/emulated/0/Download/LmsContents/" + showContentInfo.getContentTitle());
blockBlob.downloadToFile("/storage/emulated/0/Download/LmsContents/" + showContentInfo.getContentTitle());
} catch (URISyntaxException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (StorageException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
handler.post(() -> {
Toast.makeText(context, "Successful", Toast.LENGTH_SHORT).show();
});
});
}

One possible reason is that your blob file is not directly under the container. Please check in azure storage via azure portal, see if the blob file is under some subfolders within the container.
If yes(for example, the blob file is b.txt, container name is container111, and subfolder name is sub111), then you should change this line of code
CloudBlockBlob blockBlob = container.getBlockBlobReference("rblobName");
to
CloudBlockBlob blockBlob = container.getBlockBlobReference("sub111\b.txt");
And also, please check the connection string is correct or not.

Check the folder references it seems folder structure which you are providing incorrect. Just see while debugging url is correct or not .

Related

Azure CloudBlobContainer.CreateIfNotExists() throws the container already exists error with crashes webpage

I have a asp.net core app that uploads file to azure blob storage. The upload completes successfully but when CloudBlobContainer calls CreateIfNotExistAsync the web page crashes with a "The container already exists error".
var container = BlobClient.GetContainerReference(containerName.ToString().ToLower());
await container.CreateIfNotExistsAsync();
return container;
I have tried using surronding CreateIfNotExistsAsync() with the following if
if (! await container.ExistsAsync())
but that still errors.
The container name and the AccountName= in the connection string is lowercase.
I am using the latest stable Microsoft.Azure.Storage.Blob NuGet package 10.0.2
I have tried to catch the StroageExeception but the exception is not called
try
{
await container.CreateIfNotExistsAsync();
}
catch (StorageException ex)
{
Logger.LogError(ex.ToString());
}
I have been through all the points in this previous question but none of them apply/work in my scenario Azure Blob 400 Bad request on Creation of container
public class CloudBlobStorageProvider : ICloudBlobStorageProvider
{
private CloudBlobClient BlobClient { get; }
private ILogger Logger { get; }
public CloudBlobStorageProvider(IConfiguration configuration, ILogger<CloudBlobStorageProvider> logger)
{
var connectionString = configuration.GetConnectionString("AzureStorageAccount");
if (!CloudStorageAccount.TryParse(connectionString, out CloudStorageAccount storageAccount))
{
logger.LogError($"The supplied connection string for Azure blob storage could not be parsed: {connectionString}");
}
BlobClient = storageAccount.CreateCloudBlobClient();
}
public async Task<CloudBlobContainer> GetContainerAsync(CloudBlobContainerName containerName)
{
var container = BlobClient.GetContainerReference(containerName.ToString().ToLower());
await container.CreateIfNotExistsAsync(BlobContainerPublicAccessType.Off, null, null);
return container;
}
}
public interface ICloudBlobStorageProvider
{
Task<CloudBlobContainer> GetContainerAsync(CloudBlobContainerName containerName);
}
Which is called by
public async Task<CloudBlockBlob> UploadServiceUserAttachmentAsync(IFormFile formFile)
{
var fileExtenion = RegularExpressionHelpers.GetFileExtension(formFile.FileName);
string attachmentFileName = (string.IsNullOrEmpty(fileExtenion)) ? $"{Guid.NewGuid().ToString()}" : $"{Guid.NewGuid().ToString()}{fileExtenion}";
var userAttachmentContainer = await CloudBlobStorageProvider.GetContainerAsync(CloudBlobContainerName.userattachments);
var blobBlockReference = userAttachmentContainer.GetBlockBlobReference(attachmentFileName);
try
{
using (var stream = formFile.OpenReadStream())
{
await blobBlockReference.UploadFromStreamAsync(stream);
await blobBlockReference.FetchAttributesAsync();
var blobProperties = blobBlockReference.Properties;
blobProperties.ContentType = formFile.ContentType;
await blobBlockReference.SetPropertiesAsync();
}
}
catch (Exception e)
{
Logger.LogWarning(e, $"Exception encountered while attempting to write profile photo to blob storage");
}
return blobBlockReference;
}

How to download Azure BLOB?

I am not able to download azure blob file to my local disk. Please find below the java code I am using to download the file. When I run and do a HTTP trigger test, I do not see the file downloaded into my Local path. Also, I have given the authentication as public access.And , I am able to read the contents of the txt file using the blob.downloadText(). But I am not able to download it to a file.
My requirement is to download a pdf in the Blob Storage to my Local Disk.
#FunctionName("BlobDownload-Java")
public void run1(
#HttpTrigger(name = "req", methods = {HttpMethod.GET, HttpMethod.POST}, authLevel = AuthorizationLevel.FUNCTION) HttpRequestMessage<Optional<String>> request,
final ExecutionContext context) {
context.getLogger().info("Java HTTP trigger processed a request.");
try {
// Retrieve storage account from connection-string.
CloudStorageAccount storageAccount = CloudStorageAccount.parse(storageConnectionString);
// Create the blob client.
CloudBlobClient blobClient = storageAccount.createCloudBlobClient();
// Get a reference to a container.
// The container name must be lower case
CloudBlobContainer container = blobClient.getContainerReference("doccontainer");
CloudBlockBlob blob1 = container.getBlockBlobReference("AssembledDoc.pdf");
context.getLogger().info("File Name Check 1 ----->" + blob1.getName());
CloudBlockBlob blob2 = container.getBlockBlobReference("Test.txt");
String s= blob2.downloadText();
context.getLogger().info("Text Document content ----->" + s );
File file = new File("C:\\Users\\wb541348\\Project\\Temp.txt");
blob2.downloadToFile(file.getAbsolutePath());
If you just want to download PDF file to local, here is my test code , you could have a try.
#Test
public void downloadBlob(){
try {
CloudStorageAccount storageAccount = CloudStorageAccount.parse(storageConnectionString);
//Create the service client object for credentialed access to the Blob service.
CloudBlobClient blobClient = storageAccount.createCloudBlobClient();
// Retrieve a reference to a container.
CloudBlobContainer container = blobClient.getContainerReference("blobcontainer");
CloudBlob blob1 =container.getBlockBlobReference("thinking-in-java.pdf");
blob1.download(new FileOutputStream("C:\\Users\\georgec\\Documents\\" + blob1.getName()));
} catch (URISyntaxException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (StorageException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
If you still have questions, please let me know.
#Prasanna, Your can't download the blob into your localpath because the pattern of your path is wrong, it should be "c:/Users/wb541348/Project/Temp.txt", there is another point to pay attention, that is the filename is needed, which means that path shouldn't be only folder, hope it benefits.
you can also click this sample of azure blob for java sdk for reference.

How do I upload multiple files to Azure blob storage using an ID parameter as a container?

I've created a storage account on Azure for uploading files to. I am using KenoUI Async upload widget which allows multiple file uploads. What I'd like to do is have the system create a container based on the passing in Id parameter if it doesn't already exist.
I'm struggling with the actual upload part however, I'm not sure how to pass the enumerable files to the storage account. Here is my code so far:
public ActionResult Async_Save(IEnumerable<HttpPostedFileBase> files, string id)
{
//Connect to Azure
CloudStorageAccount storageAccount = CloudStorageAccount.Parse(CloudConfigurationManager.GetSetting("my_AzureStorageConnectionString"));
//Create Blob Client
CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
//Retrieve a reference to a container
CloudBlobContainer blobContainer = blobClient.GetContainerReference("vehicle_" + id);
try
{
// Create the container if it doesn't already exist
blobContainer.CreateIfNotExists();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
Console.WriteLine(ex.InnerException);
}
foreach (var file in files)
{
//This doesn't seem right to me and it's where I'm struggling
var fileName = Path.GetFileName(file.FileName);
var physicalPath = Path.Combine(blobContainer, fileName);
file.SaveAs(physicalPath);
}
// Return an empty string to signify success
return Content("");
}
What I've attempted to do is create a method that connects to my Azure storage account and:
Check for the existence of a container with the same ID as the
the parameter that's passed in, if it doesn't exist, create it.
Upload the files to the existing or newly created directory and give them a prefix of the ID i.e. "_".
As Gaurav Mantri said above, we will need to use Azure Storage SDK.
For better performance, we can do as below:
Parallel.ForEach(files, file =>
{
CloudBlockBlob blob = blobContainer.GetBlockBlobReference(file.FileName);
blob.UploadFromStream(file.InputStream);
file.InputStream.Close();
});
Your code will be better as below:
public ActionResult Async_Save(List<HttpPostedFileBase> files, string id)
{
// Connect to Azure
CloudStorageAccount storageAccount = CloudStorageAccount.Parse(CloudConfigurationManager.GetSetting("my_AzureStorageConnectionString"));
try
{
//Create Blob Client
CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
//Retrieve a reference to a container
CloudBlobContainer blobContainer = blobClient.GetContainerReference("vehicle_" + id);
// Create the container if it doesn't already exist
blobContainer.CreateIfNotExists();
Parallel.ForEach(files, file =>
{
CloudBlockBlob blob = blobContainer.GetBlockBlobReference(file.FileName);
blob.UploadFromStream(file.InputStream);
file.InputStream.Close();
});
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
Console.WriteLine(ex.InnerException);
}
// Return an empty string to signify success
return new ContentResult();
}
More information about how to use Azure Storage SDK, we can refer to:
Get Quick Start with Storage SDK
To upload a blob in Azure Storage, you will need to use Azure Storage SDK.
Please replace the following code:
foreach (var file in files)
{
//This doesn't seem right to me and it's where I'm struggling
var fileName = Path.GetFileName(file.FileName);
var physicalPath = Path.Combine(blobContainer, fileName);
file.SaveAs(physicalPath);
}
With something like:
foreach (var file in files)
{
var blob = blobContainer.GetBlockBlobReference(file.FileName);
using (var s = file.InputStream)
{
blob.UploadFromStream(s);
}
}

How to download files from Azure BLOB storage from ASP.NET MVC5

I have the ability to download files from my Azure Blob storage from a web application.
Once I get my Azure Blob storage list back, it's not downloaded.
Error entering download blob.
I would appreciate it if you could look at my code and let me know what the problem is.
public string DownloadBlob()
{
CloudBlobContainer container = GetCloudBlobContainer();
CloudBlockBlob blob = container.GetBlockBlobReference("myBlob");
using (var fileStream = System.IO.File.OpenWrite(#"C:\BlobTest"))
{
blob.DownloadToStream(fileStream);
}
return "success!";
}
I have tested your code and it works in my MVC web application as below.
public ActionResult Download()
{
ContentResult contentResult = new ContentResult();
contentResult.Content = DownloadBlob();
return contentResult;
}
public static string DownloadBlob()
{
try
{
CloudStorageAccount storageAccount = CloudStorageAccount.Parse("DefaultEndpointsProtocol=https;AccountName=leeliublob;AccountKey=O7xB6ebGq8e86XQSy2vkvSi/x/e9l9FhLqayXcbz1R+E0mIcJ5Wjkly1DsQPYY5dF2JrAVHtBozbJo29ZrrGJA==;EndpointSuffix=core.windows.net");
CloudBlobClient cloudBlobClient = storageAccount.CreateCloudBlobClient();
CloudBlobContainer container = cloudBlobClient.GetContainerReference("mycontainer");
CloudBlockBlob blob = container.GetBlockBlobReference("4.PNG");
using (var fileStream = System.IO.File.OpenWrite(#"C:\Test\BlobTest.PNG"))
{
blob.DownloadToStream(fileStream);
}
return "success!";
}
catch(Exception ex)
{
return ex.StackTrace;
}
}
I think this is the problem about the permission of your MVC application.
Your MVC application may use a virtual account of IIS as below, it may have no access to your C disk.
To solve this problem, here is two ways:
Please try to download to other disk like "E" or "D".
Please add the user group "Authenticated Users" to that file or folder like below.
Update:
I have reproduced your problem as below:
We need to create a folder under root directory of C disk as below, because your web application doesn't have the permission to the root directory of C disk:

C# Azure storage from one blob copy file to another blob

How can I read a file to stream from one blob and upload to another blob? My requirement is to copy a file from one blob to another blob with different file name? In C#
The easiest way to achieve it is using "Azure Storage Data Movement Library" (you can get it thru nuget package).
This is a simple-sample to make the transfer:
using Microsoft.WindowsAzure.Storage;
using Microsoft.WindowsAzure.Storage.Blob;
using Microsoft.WindowsAzure.Storage.DataMovement;
using System;
namespace BlobClient
{
class Program
{
static void Main(string[] args)
{
const string storageConnectionString = "DefaultEndpointsProtocol=https;AccountName=juanktest;AccountKey=loHQwke4lSEu1p2W3gg==";
const string container1 = "juankcontainer";
const string sourceBlobName = "test.txt";
const string destBlobName = "newTest.txt";
//Setup Account, blobclient and blobs
CloudStorageAccount account = CloudStorageAccount.Parse(storageConnectionString);
CloudBlobClient blobClient = account.CreateCloudBlobClient();
CloudBlobContainer blobContainer = blobClient.GetContainerReference(container1);
blobContainer.CreateIfNotExists();
CloudBlockBlob sourceBlob = blobContainer.GetBlockBlobReference(sourceBlobName);
CloudBlockBlob destinationBlob = blobContainer.GetBlockBlobReference(destBlobName);
//Setup data transfer
TransferContext context = new TransferContext();
Progress<TransferProgress> progress = new Progress<TransferProgress>(
(transferProgress) => {
Console.WriteLine("Bytes uploaded: {0}", transferProgress.BytesTransferred);
});
context.ProgressHandler = progress;
// Start the transfer
try
{
TransferManager.CopyAsync(sourceBlob, destinationBlob,
false /* isServiceCopy */,
null /* options */, context);
}
catch (Exception e)
{
Console.WriteLine("The transfer is cancelled: {0}", e.Message);
}
Console.WriteLine("CloudBlob {0} is copied to {1} ====successfully====",
sourceBlob.Uri.ToString(),
destinationBlob.Uri.ToString());
Console.ReadLine();
}
}
}
Note that "Azure Storage Data Movement Library" is very robust so you can track the transfer progress, cancel the operation or even suspend it to resume it later ;)
One of the easiest ways to copy files is with the AzCopy utility.
I would like to recommend another method other than the above to get this done.
That is azure functions. (serverless compute service).
As a prerequisite, you should have some knowledge in azure functions, creating them, deploying them. 1. What is azure function 2. create an Azure function app
And the following code snippet is the simplest and basic way to perform this action. (In here, when a user uploading a new file to the "demo" blob, the function will be triggered and read that uploaded file from the demo blob and copy to the "output" blob.)
namespace Company.Function{
public static class NamalFirstBlobTrigger
{
[FunctionName("NamalFirstBlobTrigger")]
public static void Run([BlobTrigger("demo/{name}", Connection = "AzureWebJobsStorage")]Stream myBlob,
[Blob("output/testing.cs",FileAccess.Write, Connection = "AzureWebJobsStorage")]Stream outputBlob,
string name,
ILogger log)
{
myBlob.CopyTo(outputBlob);
}
}}

Resources