I try to get properties after or before download by BlobHelper.GetBlobReference() for loging , at last I try with blob.FetchAttributes(); but doestn work my properties are null. My container and my blob have not permissions
public static CloudBlob GetBlobReference(string containerName,string fileName)
{
var blobClient = GetBlobClient();
if (blobClient != null)
{
var contRef=blobClient.GetContainerReference(containerName);
return contRef.GetBlobReference(fileName);
}
return null;
}
var blob = BlobHelper.GetBlobReference(SelectedContainer,
fileName);
if (blob.Properties != null)
{
//I try to get Lenght of blob but it is -1
}
This is expected behavior. GetBlobReference simply creates an instance of CloudBlob on the client and doesn't make a network request. From the documentation link:
Call this method to return a reference to a blob of any type in this
container. Note that this method does not make a request against Blob
storage. You can return a reference to the blob whether or not it
exists yet.
If you want to get the properties populated, you must call FetchAttributes or use GetBlobReferenceFromServer.
Related
I am writing a service that uploads / downloads items from Azure Blob storage. When I upload a file I set the ContentType.
public async Task UploadFileStream(Stream filestream, string filename, string contentType)
{
CloudBlockBlob blockBlobImage = this._container.GetBlockBlobReference(filename);
blockBlobImage.Properties.ContentType = contentType;
blockBlobImage.Metadata.Add("DateCreated", DateTime.UtcNow.ToLongDateString());
blockBlobImage.Metadata.Add("TimeCreated", DateTime.UtcNow.ToLongTimeString());
await blockBlobImage.UploadFromStreamAsync(filestream);
}
However when I retrieve the file the ContentType is null.
public async Task<CloudBlockBlob> GetBlobItem(string filename)
{
var doesBlobExist = await this.DoesBlobExist(filename);
return doesBlobExist ? this._container.GetBlockBlobReference(filename) : null;
}
In my code that uses these methods I check the ContentType of the returned Blob but it is null.
var blob = await service.GetBlobItem(blobname);
string contentType = blob.Properties.ContentType; //this is null!
I have tried using the SetProperties() method in my UploadFileStream() method (above) but this doesn't work either.
CloudBlockBlob blockBlobImage = this._container.GetBlockBlobReference(filename);
blockBlobImage.Properties.ContentType = contentType;
blockBlobImage.SetProperties(); //adding this has no effect
blockBlobImage.Metadata.Add("DateCreated", DateTime.UtcNow.ToLongDateString());
blockBlobImage.Metadata.Add("TimeCreated", DateTime.UtcNow.ToLongTimeString());
await blockBlobImage.UploadFromStreamAsync(filestream);
So how do I set the ContentType for a blob item in Azure Blob storage?
The problem is with the following line of code:
this._container.GetBlockBlobReference(filename)
Essentially this creates an instance of CloudBlockBlob on the client side. It does not make any network calls. Because this method simply creates an instance on the client side, all the properties are initialized with default values and that's why you see the ContentType property as null.
What you would need to do is actually make a network call to fetch blob's properties. You can call FetchAttributesAsync() method on CloudBlockBlob object and then you will see the ContentType property filled in properly.
Please keep in mind that FetchAttributesAsync method can throw an error (e.g. 404 in case blob does not exists) so please ensure that the call to this method is wrapped in try/catch block.
You can try code like something below:
public async Task<CloudBlockBlob> GetBlobItem(string filename)
{
try
{
var blob = this._container.GetBlockBlobReference(filename);
await blob.FetchAttributesAsync();
return blob;
}
catch (StorageException exception)
{
return null;
}
}
I am using Azure storage to store and retrieve images. I have this method to save an image (blob):
public void SaveBlob(string containerName, string blobName, byte[] blob)
{
// Retrieve reference to the blob
CloudBlockBlob blockBlob = GetContainer(containerName, true).GetBlockBlobReference(blobName);
using (var stream = new MemoryStream(blob, writable: false))
{
blockBlob.UploadFromStream(stream);
}
}
This is the GetContainer method:
public CloudBlobContainer GetContainer(string containerName, bool createIfNotExist)
{
if (string.IsNullOrEmpty(containerName))
return null;
// Retrieve a reference to a container. If container doesn't exist, optionally create it.
CloudBlobContainer container = this._blobClient.GetContainerReference(containerName);
if (container == null && !createIfNotExist)
return null;
// Create the container if it doesn't already exist. It will be private by default.
container.CreateIfNotExists(BlobContainerPublicAccessType.Off, null, null);
return container;
}
What's happening here is that when I attempt to save a blob, I get a reference to a container first. If the container doesn't exist, it is created, and then the blob is saved. Will I run into timing issues here if I have to create the container first and then save a blob to it immediately? My concern is that I might be attempting to save the blob to the container before Azure is finished creating it. Or maybe this isn't an issue?
Looking at your code, I don't think you will run into any timing issues because CreateIfNotExists method is a sync method and will only return when the container is created. Also with Azure Blob Storage (unlike Amazon S3), the method will either create the container immediately or throw an error if it fails to do so (or in other words Azure Storage is Strongly Consistent).
Also I think this piece of code is redundant:
if (container == null && !createIfNotExist)
return null;
As container will never be equal to null and thus this if condition will never be true.
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.
I am trying to rename blob in azure storage via .net API and it is I am unable to rename a blob file after a day : (
Here is how I am doing it, by creating new blob and copy from old one.
var newBlob = blobContainer.GetBlobReferenceFromServer(filename);
newBlob.StartCopyFromBlob(blob.Uri);
blob.Delete();
There is no new blob on server so I am getting http 404 Not Found exception.
Here is working example that i have found but it is for old .net Storage api.
CloudBlob blob = container.GetBlobReference(sourceBlobName);
CloudBlob newBlob = container.GetBlobReference(destBlobName);
newBlob.UploadByteArray(new byte[] { });
newBlob.CopyFromBlob(blob);
blob.Delete();
Currently I am using 2.0 API. Where I am I making a mistake?
I see that you're using GetBlobReferenceFromServer method to create an instance of new blob object. For this function to work, the blob must be present which will not be the case as you're trying to rename the blob.
What you could do is call GetBlobReferenceFromServer on the old blob, get it's type and then either create an instance of BlockBlob or PageBlob and perform copy operation on that. So your code would be something like:
CloudBlobContainer blobContainer = storageAccount.CreateCloudBlobClient().GetContainerReference("container");
var blob = blobContainer.GetBlobReferenceFromServer("oldblobname");
ICloudBlob newBlob = null;
if (blob is CloudBlockBlob)
{
newBlob = blobContainer.GetBlockBlobReference("newblobname");
}
else
{
newBlob = blobContainer.GetPageBlobReference("newblobname");
}
//Initiate blob copy
newBlob.StartCopyFromBlob(blob.Uri);
//Now wait in the loop for the copy operation to finish
while (true)
{
newBlob.FetchAttributes();
if (newBlob.CopyState.Status != CopyStatus.Pending)
{
break;
}
//Sleep for a second may be
System.Threading.Thread.Sleep(1000);
}
blob.Delete();
The code in OP was almost fine except that an async copy method was called. The simplest code in new API should be:
var oldBlob = cloudBlobClient.GetBlobReferenceFromServer(oldBlobUri);
var newBlob = container.GetBlobReference("newblobname");
newBlog.CopyFromBlob(oldBlob);
oldBlob.Delete();
Is there a way to know if a blob file exists inside a container without getting the whole list of blob objects ?
Thanks,
If you know the address of the blob, a tip from the Azure SDK is to first build a CloudBlockBlob (or a CloudPageBlob) and then call FetchAttributes. This call will throw a StorageClientException if it cannot locate the blob.
From the CloudBlobClient.GetBlockBlobReference documentation:
The FetchAttributes method executes a HEAD request to populate the
blob's properties and metadata and as such is a lightweight option for
determining whether the blob exists.
Starting from Windows Azure Storage Client Library 2.0, the blob contains method Exists(), e.g: blob.Exists()
the same is true for the BlobContainer.
This is the code that I'm using
public static bool Exists(this CloudBlob blob)
{
try
{
blob.FetchAttributes();
return true;
}
catch (StorageClientException e)
{
if (e.ErrorCode == StorageErrorCode.ResourceNotFound)
{
return false;
}
else
{
throw;
}
}
}