I am using Azure storage blob to store image and I am trying to display it in my Xamrin.form application. I have find a simple tutorial and the code on github.
I have succeed to implement it by following the steps and and create an account on azure storage blob.
The problem is : I can see the name of the file but not the "image"
here is the error:
read started: <Thread Pool> #9
[0:] HTTP Request: Could not retrieve https://xxxxxx.blob.core.windows.net/yyyy/kakashi.jpg, status code NotFound
[0:] ImageLoaderSourceHandler: Could not retrieve image or image data was invalid: Uri: https://lxxxxxx.blob.core.windows.net/yyyy/kakashi.jpg
Thread finished: <Thread Pool> #4
Here is the tutorial:
click to see
Here is the Github:
click to see
Here is the output on screen:
and I have this error when I put the Urlof the image (https://lxxxxxx.blob.core.windows.net/yyyy/kakashi.jpg
) on my bronwser:
This XML file does not appear to have any style information associated with it. The document tree is shown below.
<Error>
<Code>ResourceNotFound</Code>
<Message>
The specified resource does not exist. RequestId:97933c69-a01e-014f-6669-f0502e000000 Time:2018-05-20T18:33:28.4774584Z
</Message>
</Error>
The error means you don't set Public access level to Blob.
See this requirement in your tutorial.
Code you use requires this setting, because it accesses the blob directly using blob Uri.
See PhotosBlobStorageService.cs
return blobList.Select(x => new PhotoModel { Title = x.Name, Uri = x.Uri }).ToList();
If you do want to keep Private level, you have to make some changes to the statement above. Here's the reference.
return blobList.Select(x => new PhotoModel { Title = x.Name,
Uri = new Uri(x.Uri+x.GetSharedAccessSignature(
new SharedAccessBlobPolicy {
Permissions = SharedAccessBlobPermissions.Read|SharedAccessBlobPermissions.Write,
// you can modify the expiration to meet your requirement
SharedAccessExpiryTime = DateTime.UtcNow.AddYears(1)
} ))
}).ToList();
This change allows you to visit private blob with a SAS.
1.Please check your subscription first.
2.Check the access policy of your container.
3.Here is the steps to Save and get blobs through the code.
1)Using NuGet we can install required Assembly packages.
Go to "Manage Package for Solution Menu" and search for WindowsAzure.Storage and WindowsAzure.ConfigurationManager and click on install.
2)Get access keys in the configuration.
3)Sample code to Create blob through the code:
public async Task<string> SaveImagesToAzureBlob(HttpPostedFileBase imageToUpload)
{
try
{
CloudStorageAccount cloudStorageAccount = CloudStorageAccount.Parse(CloudConfigurationManager.GetSetting("StorageConnectionString"));
CloudBlobClient cloudBlobClient = cloudStorageAccount.CreateCloudBlobClient();
CloudBlobContainer cloudBlobContainer = cloudBlobClient.GetContainerReference("sampleimage");
if (await cloudBlobContainer.CreateIfNotExistsAsync())
{
await cloudBlobContainer.SetPermissionsAsync(
new BlobContainerPermissions
{
PublicAccess = BlobContainerPublicAccessType.Blob
}
);
}
string imageFullPath = null;
string imageName = Guid.NewGuid().ToString() + "-" + Path.GetExtension(imageToUpload.FileName);
CloudBlockBlob cloudBlockBlob = cloudBlobContainer.GetBlockBlobReference(imageName);
cloudBlockBlob.Properties.ContentType = imageToUpload.ContentType;
await cloudBlockBlob.UploadFromStreamAsync(imageToUpload.InputStream);
imageFullPath = cloudBlockBlob.Uri.ToString();
return imageFullPath;
}
catch (Exception ex)
{
throw ex;
}
}
Now, check your storage account, you can see the container sample generated.
By default, the container will be private, no one can access from outside. To set the permissions we should use the SetPermission method as below.
CloudBlobContainer .SetPermissions( new BlobContainerPermissions { PublicAccess = BlobContainerPublicAccessType.Blob });
Please try different permissions in the list.
Please note the permission level settings.In your case it may cause the issue.
For more details :
Reference
https://learn.microsoft.com/en-us/azure/azure-resource-manager/resource-manager-deployment-model
https://learn.microsoft.com/en-us/azure/storage/blobs/storage-dotnet-how-to-use-blobs
Related
My code below uploads an Excel file from a user's form submission. However, I'd like to work with the Excel file using EPplus to write it to the database. For that, I need the file's address on the disk, rather than the web address. How can I get that?
Relevant code:
{
public class ExcelService
{
public async Task<string> UploadExcelAsync(HttpPostedFileBase upload)
{
string excelFullPath = null;
if (upload == null || upload.ContentLength == 0)
{
return null;
}
try
{
CloudStorageAccount cloudStorageAccount = ConnectionString.GetConnectionString();
CloudBlobClient cloudBlobClient = cloudStorageAccount.CreateCloudBlobClient();
CloudBlobContainer cloudBlobContainer = cloudBlobClient.GetContainerReference("excel");
if (await cloudBlobContainer.CreateIfNotExistsAsync())
{
await cloudBlobContainer.SetPermissionsAsync(
new BlobContainerPermissions
{
PublicAccess = BlobContainerPublicAccessType.Blob
}
);
}
string excelName = Guid.NewGuid().ToString() + "-" + Path.GetExtension(upload.FileName);
CloudBlockBlob cloudBlockBlob = cloudBlobContainer.GetBlockBlobReference(excelName);
cloudBlockBlob.Properties.ContentType = upload.ContentType;
await cloudBlockBlob.UploadFromStreamAsync(upload.InputStream);
excelFullPath = cloudBlockBlob.Uri.ToString();
}
catch (Exception ex)
{
}
return excelFullPath;
}
}
}
You can't. Azure Storage Blobs is a cloud service that only exposes web access to the stored blobs, so there is no physical location on a disk you can access. So unless you download the file, edit it and upload it again there is not way to edit it directly.
An alternative could be to use Azure Storage Files. Still an Azure Cloud based service for storage but it allows you to map folders to your machine so you can access it like any network share. See the docs. This, of course, only works if you are able to create a file share on the web server.
Unfortunately you cannot access Azure Storage Files shares using Azure Web Apps (source) so if that it how your web app is hosted than you are out of luck for that.
I had my project working in Core 1, but when I changed to Core 2 it,no longer uploads the images to Azure.I get a 404 response code and "Problem sending file to Azure" message. The correct URL is returned from the server, but then,finuploader calls a URL with current URL in Front
The URL in chrome Console returning the 404 is shown as
https://localhost:44348/House/%22https://Customstorage.blob.core.windows.net/images/b0975cc7-fae5-4130-bced-c26272d0a21c.jpeg?sv=2017-04-17&sr=b&sig=UFUEsHT1GWI%2FfMd9cuHmJsl2j05W1Acux52UZ5IsXso%3D&se=2017-09-16T04%3A06%3A36Z&sp=rcwd%22
This is being added to the URL somewhere
https://localhost:44348/House/%22
I create the SAS with
public async Task<string> SAS(string bloburi, string name)
{
CloudStorageAccount storageAccount = new CloudStorageAccount(
new Microsoft.WindowsAzure.Storage.Auth.StorageCredentials(
"<storage-account-name>",
"<access-key>"), true)
CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
CloudBlobContainer container = blobClient.GetContainerReference("images");
return await Task.FromResult<string>(GetBlobSasUri(container, bloburi));
}
private static string GetBlobSasUri(CloudBlobContainer container, string blobName, string policyName = null)
{
string sasBlobToken;
// Get a reference to a blob within the container.
// Note that the blob may not exist yet, but a SAS can still be created for it.
var uri = new Uri(blobName);
//get the name of the file from the path
string filename = System.IO.Path.GetFileName(uri.LocalPath);
CloudBlockBlob blob = container.GetBlockBlobReference(filename);
if (policyName == null)
{
// Create a new access policy and define its constraints.
// Note that the SharedAccessBlobPolicy class is used both to define the parameters of an ad-hoc SAS, and
// to construct a shared access policy that is saved to the container's shared access policies.
SharedAccessBlobPolicy adHocSAS = new SharedAccessBlobPolicy()
{
// When the start time for the SAS is omitted, the start time is assumed to be the time when the storage service receives the request.
// Omitting the start time for a SAS that is effective immediately helps to avoid clock skew.
SharedAccessExpiryTime = DateTime.UtcNow.AddHours(1),
Permissions = SharedAccessBlobPermissions.Read | SharedAccessBlobPermissions.Write | SharedAccessBlobPermissions.Create | SharedAccessBlobPermissions.Delete
};
// Generate the shared access signature on the blob, setting the constraints directly on the signature.
sasBlobToken = blob.GetSharedAccessSignature(adHocSAS);
}
else
{
// Generate the shared access signature on the blob. In this case, all of the constraints for the
// shared access signature are specified on the container's stored access policy.
sasBlobToken = blob.GetSharedAccessSignature(null, policyName);
}
// Return the URI string for the container, including the SAS token.
return blob.Uri + sasBlobToken;
}
Fine-uploader -
var uploader = new qq.azure.FineUploader({
element: document.getElementById('uploader'),
template: 'qq-template',
autoUpload: false,
request: {
endpoint:'https://customstorage.blob.core.windows.net/images'
},
signature: {
endpoint: '/House/SAS'
},
uploadSuccess: {
endpoint: '/House/UploadImage'
}
});
I am presently working with windows 10 universal application, here i am working with azure storage.
I am getting above error when i downloading file file from windows azure storage.
Here is my download code:
private async Task<int> DownloadFromAzureStorage()
{
try
{
// create Azure Storage
CloudStorageAccount storageAccount = CloudStorageAccount.Parse("DefaultEndpointsProtocol=https;AccountName=<myaccname>;AccountKey=<mykey>");
// create a blob client.
CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
// create a container
CloudBlobContainer container = blobClient.GetContainerReference("sample");
await container.CreateIfNotExistsAsync();
// create a block blob
CloudBlockBlob blockBlob = container.GetBlockBlobReference("abc.jpg");
FileSavePicker openPicker = new FileSavePicker();
openPicker.SuggestedStartLocation = PickerLocationId.PicturesLibrary;
openPicker.FileTypeChoices.Add("File", new List<string>() { ".jpg" });
openPicker.SuggestedFileName = "New Documents";
var imgFile = await openPicker.PickSaveFileAsync();
await blockBlob.DownloadToFileAsync(imgFile); **//Error occuring in this line**
return 1;
}
catch
{
// return error
return 0;
}
}
File Uploading to my azure storage is success, but when i download to my uploaded my it showing the error is "An unhandled exception of type 'System.StackOverflowException' occurred in Microsoft.WindowsAzure.Storage.dll" in await blockBlob.DownloadToFileAsync(imgFile); Line
please help me to resolve this issue..
This is a known issue with the DownloadToFileAsync() method in the Win10 Universal Storage Client (unfortunately). The bug is fixed in the current preview release (7.0.2-preview), and will be fixed in an upcoming non-preview release. To fix your issue for now, please change your DownloadToFile call to the following:
await blockBlob.DownloadToFileAsync(imgFile, null, null, null, CancellationToken.None);
I’ve read through and played with the sample code in the https://azure.microsoft.com/en-us/documentation/articles/storage-dotnet-shared-access-signature-part-2/#part-1-create-a-console-application-to-generate-shared-access-signatures
I then applied it to my scenario.
I write a tool to upload data from partner to Azure blob storage and then it will be consumed by some internal teams:
YYYY-MM (container)
(DD-GUID) (prefix)
File1.zip
File2.zip
……
I created 2 policies per container:
1. Write only for the partner so that they can only write blobs and nothing else.
2. List and read for our internal teams so that they can list and read(download) all the blobs in the container.
My thought is that I can simply hand the correct policy to the correct recipients; however, my implementation doesn’t work as I expected.
I created 2 policies for each container using the below method, of course with correct permission per policy:
static void CreateSharedAccessPolicy(CloudBlobClient blobClient, CloudBlobContainer container, string policyName)
{
//Create a new stored access policy and define its constraints.
SharedAccessBlobPolicy sharedPolicy = new SharedAccessBlobPolicy()
{
SharedAccessExpiryTime = DateTime.UtcNow.AddHours(10),
Permissions = SharedAccessBlobPermissions.Read | SharedAccessBlobPermissions.Write | SharedAccessBlobPermissions.List
};
//Get the container's existing permissions.
BlobContainerPermissions permissions = new BlobContainerPermissions();
//Add the new policy to the container's permissions.
permissions.SharedAccessPolicies.Clear();
permissions.SharedAccessPolicies.Add(policyName, sharedPolicy);
container.SetPermissions(permissions);
}
I created the write only policy first and then the read and list policy. What I observed is that the first policy doesn’t seem to work, everything got back a 403 Forbidden and for the second policy, the only thing that works is the List blob but not Read (I tried to download the blob but got a 404 Not Found).
It seems like I’ve missed something very basic here. Can you please help me out to see what’s wrong with my approach?
The code I used to test the permissions of the container, I also notice that the Read permission on a container doesn't really work as mentioned somewhere in Azure documentation. Here I'm trying to find an easy way to simply give people a stored access policy so that they can list and download all the blobs in the container instead of providing them a signature per blob file:
static void UseContainerSAS(string sas)
{
//Try performing container operations with the SAS provided.
//Return a reference to the container using the SAS URI.
CloudBlobContainer container = new CloudBlobContainer(new Uri(sas));
//Create a list to store blob URIs returned by a listing operation on the container.
List<Uri> blobUris = new List<Uri>();
try
{
//Write operation: write a new blob to the container.
CloudBlockBlob blob = container.GetBlockBlobReference("blobCreatedViaSAS.txt");
string blobContent = "This blob was created with a shared access signature granting write permissions to the container. ";
MemoryStream msWrite = new MemoryStream(Encoding.UTF8.GetBytes(blobContent));
msWrite.Position = 0;
using (msWrite)
{
blob.UploadFromStream(msWrite);
}
Console.WriteLine("Write operation succeeded for SAS " + sas);
Console.WriteLine();
}
catch (StorageException e)
{
Console.WriteLine("Write operation failed for SAS " + sas);
Console.WriteLine("Additional error information: " + e.Message);
Console.WriteLine();
}
try
{
//List operation: List the blobs in the container, including the one just added.
foreach (ICloudBlob blobListing in container.ListBlobs())
{
blobUris.Add(blobListing.Uri);
}
Console.WriteLine("List operation succeeded for SAS " + sas);
Console.WriteLine();
}
catch (StorageException e)
{
Console.WriteLine("List operation failed for SAS " + sas);
Console.WriteLine("Additional error information: " + e.Message);
Console.WriteLine();
}
try
{
CloudBlockBlob blob = container.GetBlockBlobReference(blobUris[0].ToString());
MemoryStream msRead = new MemoryStream();
msRead.Position = 0;
using (msRead)
{
blob.DownloadToStream(msRead);
Console.WriteLine(msRead.Length);
}
Console.WriteLine("Read operation succeeded for SAS " + sas);
Console.WriteLine();
}
catch (StorageException e)
{
Console.WriteLine("Read operation failed for SAS " + sas);
Console.WriteLine("Additional error information: " + e.Message);
Console.WriteLine();
}
Console.WriteLine();
try
{
//Delete operation: Delete a blob in the container.
CloudBlockBlob blob = container.GetBlockBlobReference(blobUris[0].ToString());
blob.Delete();
Console.WriteLine("Delete operation succeeded for SAS " + sas);
Console.WriteLine();
}
catch (StorageException e)
{
Console.WriteLine("Delete operation failed for SAS " + sas);
Console.WriteLine("Additional error information: " + e.Message);
Console.WriteLine();
}
}
Actually, your latter operation erased what you did in the first operation. To avoid that, you ought to read the existing permissions of the container, add a new permission, then set the permissions back to container.
Following is the correct code sample:
static void CreateSharedAccessPolicy(CloudBlobClient blobClient, CloudBlobContainer container, string policyName)
{
//Create a new stored access policy and define its constraints.
SharedAccessBlobPolicy sharedPolicy = new SharedAccessBlobPolicy()
{
SharedAccessExpiryTime = DateTime.UtcNow.AddHours(10),
Permissions = SharedAccessBlobPermissions.Read | SharedAccessBlobPermissions.Write | SharedAccessBlobPermissions.List
};
//Get the container's existing permissions.
BlobContainerPermissions permissions = container.GetPermissions();
//Add the new policy to the container's permissions.
permissions.SharedAccessPolicies.Add(policyName, sharedPolicy);
container.SetPermissions(permissions);
}
For the reason why you were confronting 404 error for reading blobs, please share you code of creating SAS by policy and how you use the created SAS to read blobs so that I can help trouble-shoot.
Following is a code sample for creating SAS and using it to read blobs: (you can copy+paste the URLs in stdout to browser directly to have a try)
var permissions = container.GetPermissions();
var policy = new SharedAccessBlobPolicy
{
Permissions = SharedAccessBlobPermissions.Read,
SharedAccessExpiryTime = DateTime.UtcNow.AddYears(1),
};
string policyName = "read";
permissions.SharedAccessPolicies.Add(policyName, policy);
container.SetPermissions(permissions);
string sas = container.GetSharedAccessSignature(null, policyName);
var blobs = container.ListBlobs(null, true);
Console.WriteLine("SAS = {0}", sas);
Console.WriteLine("Blobs URLs with SAS:");
foreach (var blob in blobs)
{
Console.WriteLine(blob.Uri.ToString() + sas);
}
I've been trying to create a Windows Azure Blob containing an image file. I followed these tutorials: http://www.nickharris.net/2012/11/how-to-upload-an-image-to-windows-azure-storage-using-mobile-services/ and http://www.windowsazure.com/en-us/develop/mobile/tutorials/upload-images-to-storage-dotnet/. Finally the following code represents a merging of them. On the last line, however, an exception is raised:
An exception of type 'System.TypeLoadException' occurred in
mscorlib.ni.dll but was not handled in user code
Additional information: A binding for the specified type name was not
found. (Exception from HRESULT: 0x80132005)
Even the container is created the table, but It doesn't work properly.
private async void SendPicture()
{
StorageFile media = await StorageFile.GetFileFromPathAsync("fanny.jpg");
if (media != null)
{
//add todo item to trigger insert operation which returns item.SAS
var todoItem = new Imagem()
{
ContainerName = "mypics",
ResourceName = "Fanny",
ImageUri = "uri"
};
await imagemTable.InsertAsync(todoItem);
//Upload image direct to blob storage using SAS and the Storage Client library for Windows CTP
//Get a stream of the image just taken
using (var fileStream = await media.OpenStreamForReadAsync())
{
//Our credential for the upload is our SAS token
StorageCredentials cred = new StorageCredentials(todoItem.SasQueryString);
var imageUri = new Uri(todoItem.SasQueryString);
// Instantiate a Blob store container based on the info in the returned item.
CloudBlobContainer container = new CloudBlobContainer(
new Uri(string.Format("https://{0}/{1}",
imageUri.Host, todoItem.ContainerName)), cred);
// Upload the new image as a BLOB from the stream.
CloudBlockBlob blobFromSASCredential =
container.GetBlockBlobReference(todoItem.ResourceName);
await blobFromSASCredential.UploadFromStreamAsync(fileStream.AsInputStream());
}
}
}
Please use Assembly Binding Log Viewer to see which load is failing. As also mentioned in the article, the common language runtime's failure to locate an assembly typically shows up as a TypeLoadException in your application.