I'm using azure storage client to upload some files to Azure blob storage. This upload is happening from a dll file stored in local machine. following is the code i'm using.
public bool UploadBlob(byte[] fileContent, CloudStorageAccount account, string containerName, string blobName)
{
try
{
CloudBlobClient blobclient = account.CreateCloudBlobClient();
CloudBlobContainer container = blobclient.GetContainerReference(containerName);
container.CreateIfNotExist();
CloudBlockBlob blob = container.GetBlockBlobReference(blobName);
HashSet<string> blocklist = new HashSet<string>();
foreach (FileBlock block in GetFileBlocks(fileContent))
{
if (ScanTool.mIsThreadStop)
return false;
ScanTool.mDocumentUploadedSize += block.Content.Length;
blob.PutBlock(
block.Id,
new MemoryStream(block.Content, true),
null
);
blocklist.Add(block.Id);
}
blob.PutBlockList(blocklist);
blob.FetchAttributes();
return blob.Properties.Length == fileContent.Length;
}
catch (Exception e) {
Log.WriteErrorLog(e, "UploadBlob at AzureBlobUtilCS");
throw new System.Net.WebException();
}
}
I'm calling above upload method as follows and it throws "Proxy Authentication failed" Exception on following code
try
{
CloudBlobContainer container = AzureHelper.GetContainer(containerName, accountName, accountKey);
CloudStorageAccount storageAccount = CloudStorageAccount.Parse(AzureHelper.GetConnectionString(accountName, accountKey));
return UploadBlob(fileContent, storageAccount, containerName, blobName);
}catch(Exception e)
{
WriteInformationMessage("exception at UploadBlob11 =" + e.Message);
return false;
}
This issue is encounter in one of my client site and he is saying they have a proxy in their local network. Proxy name is bluecoat proxy SG 900
How to get rid of this?
I was experiencing similar issues, not only in Azure Storage, but also on the entire website.
In order to disable the default proxy used by Azure Storage, which happens to be the default proxy used by the HttpClient class, I changed Web.config, by adding the defaultProxy element:
<configuration>
<system.net>
<defaultProxy enabled="false"></defaultProxy>
</system.net>
</configuration>
If you must configure the default proxy, instead of disabling it, you can also do so within that same element, according to the docs: https://msdn.microsoft.com/en-us/library/kd3cf2ex(v=vs.110).aspx
Related
I have an asp mvc application where I am trying to display images that have been stored in Azure blob storage.
When I return the string the browser just shows as a broken image. When I right click and "inspect" and click the generated URI I recieve the following message
BlobNotFound
The specified blob does not exist. RequestId:f7c32876-0001-013e-539d-dede28000000 Time:2016-07-15T13:30:49.7560775Z
I have downloaded Azure Storage Explorer and can see the file. I have tried to change the access levels on the container to read access for blobs only from no public access (but I thought I did that in code with the line PublicAccess = BlobContainerPublicAccessType.Blob).
How do I display images that are contained in storage?
public string Index()
{
CloudBlockBlob blob = GetBlobInContainer("blobContainerTjsContainer", "PS-ICON-120x120_140.jpg");
return "<img src="+ blob.Uri.AbsoluteUri +" alt='PS Image'>";
}
CloudBlockBlob GetBlobInContainer(string container, string fileName)
{
//use web.config appSetting to get connection setting .NET Framework's ConfigurationManager class can also be used for this
CloudStorageAccount storageAccount = CloudStorageAccount.Parse(CloudConfigurationManager.GetSetting("StorageConnectionString"));
//create the blob client
CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
//retrieve a refernce to a container
CloudBlobContainer blobContainer = blobClient.GetContainerReference(CloudConfigurationManager.GetSetting(container));
//set permission to show to public
blobContainer.SetPermissions(new BlobContainerPermissions { PublicAccess = BlobContainerPublicAccessType.Blob});
blobContainer.CreateIfNotExists();
// Retrieve reference to a blob named "photo1.jpg".
CloudBlockBlob blockBlob = blobContainer.GetBlockBlobReference(fileName);
return blockBlob;
}
EDIT
After further reading I have changed
// Retrieve reference to a blob named "photo1.jpg".
CloudBlockBlob blockBlob = blobContainer.GetBlockBlobReference(fileName);
return blockBlob;
to
// Retrieve reference to a blob named "photo1.jpg".
CloudBlockBlob blockBlob = blobContainer.GetBlockBlobReference(fileName);
blockBlob.Properties.ContentType = "image/jpg";
blockBlob.SetProperties();
return blockBlob;
this changes returns an exception
Exception Details: System.Net.WebException: The remote server returned an error: (404) Not Found.
Do I need to do something different at the time of uploading?
Edit
#Gaurav Mantri
I can see that it is stored as application/octet-stream but when I tried to change this to image/jpg using
blockBlob.Properties.ContentType = "image/jpg";
blockBlob.SetProperties();
I got a 404 exception at set properties. When I pull the image, while debugging I can see the image name is the same as it was when I uploaded it
at the time of uploading I used the below code
void UploadFile(string filePath)
{
//use web.config appSetting to get connection setting .NET Framework's ConfigurationManager class can also be used for this
CloudStorageAccount storageAccount = CloudStorageAccount.Parse(CloudConfigurationManager.GetSetting("StorageConnectionString"));
//create the blob client
CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
//retrieve a refernce to a container
CloudBlobContainer blobContainer = blobClient.GetContainerReference(CloudConfigurationManager.GetSetting("blobContainerTjsContainer"));
//create a container if it doesnt exist
blobContainer.CreateIfNotExists();
//gets the reference to the blob that will be written or OVER written
CloudBlockBlob blockBlob = blobContainer.GetBlockBlobReference("my-image-blob");
using (var fileStream = System.IO.File.OpenRead(filePath))
{
blockBlob.UploadFromStream(fileStream);
}
}
Thanks to the comments from Gaurav I was able to work out my problem.
I was downloading the file as below
CloudBlockBlob blockBlob = blobContainer.GetBlockBlobReference(fileName);
blockBlob.Properties.ContentType = "image/jpg";
blockBlob.SetProperties();
return blockBlob;
But when storing the file I was not setting the content type so it was being saved as application/octet-stream and the above code was trying to convert the type when calling the file. By setting the type prior to uploading I was able to simply call the file and have it displayed as an image e.g.
CloudBlockBlob blockBlob = blobContainer.GetBlockBlobReference("my-image-blob");
blockBlob.Properties.ContentType = "image/jpg";
using (var fileStream = System.IO.File.OpenRead(filePath))
{
blockBlob.UploadFromStream(fileStream);
}
I created a web app in Azure. This was a simple web app created using microsoft asp .net. I downloaded my azure profile and published to the azure web app using visual studio. There is an image folder in the web app. When I published all the images uploaded like a charm. Then I used a WPF smartclient app using a web client object and set its Credentials to network credentials along with the user id and the password of my azure account. But when the line reaches the webclient.upload kind of method, I am getting a 401 unauthorized exception. It looks to me that when I try to upload my credentails are not taken as correct. If it were IIS, I know what to do. But in AZURE I am not sure how I can give an anonymous user and access to upload the image. Any comments or points to be considered here?
If your images are not a static part of your application but instead they can be created from your application (example user uploading his picture) I would recommend using Azure Storage instead of file system (you wont loose images uploaded by your users after you do next deploy).
Azure Storage can be easily managed both from code as well as using GUI management tools like CloudBerry Explorer.
adding name space
using Microsoft.WindowsAzure.Storage;
using Microsoft.WindowsAzure.Storage.Auth;
using Microsoft.WindowsAzure.Storage.Blob;
2.Adding class
public class blobservice
{
public CloudBlobContainer GetCloudBlobContainer()
{
string connString = "DefaultEndpointsProtocol=https;AccountName="";AccountKey=E"";";
string destContainer = "mysample";
CloudStorageAccount storageAccount = CloudStorageAccount.Parse(connString);
CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
CloudBlobContainer blobContainer = blobClient.GetContainerReference(destContainer);
if (blobContainer.CreateIfNotExists())
{
blobContainer.SetPermissions(new BlobContainerPermissions
{
PublicAccess = BlobContainerPublicAccessType.Blob
});
}
return blobContainer;
}
}
3..aspx.cs
blobservice _blobServices = new blobservice();
protected void Page_Load(object sender, EventArgs e)
{
blobservice _blobServices = new blobservice();
Upload();
}
public void Upload()
{
CloudBlobContainer blobContainer = _blobServices.GetCloudBlobContainer();
CloudBlockBlob blob = blobContainer.GetBlockBlobReference("Sampleblob.jpg");
WebClient wc = new WebClient();
byte[] bytes = wc.DownloadData(Server.MapPath("~/Images/active.png"));
using (Stream ms = new MemoryStream(bytes))
{
blob.UploadFromStream(ms);
}
}
protected void btnDelete_Click(object sender, EventArgs e)
{
string Name = "https://bikeimages.blob.core.windows.net/mysample/Sampleblob.jpg";
Uri uri = new Uri(Name);
string filename = System.IO.Path.GetFileName(uri.LocalPath);
blobservice _blobServices = new blobservice();
CloudBlobContainer blobContainer = _blobServices.GetCloudBlobContainer();
CloudBlockBlob blob = blobContainer.GetBlockBlobReference(filename);
blob.Delete();
}
I have created a Service bus queue. The URL for this is:
https://ns-eventqueue.servicebus.windows.net/eventqueue
I have also created a Shared Access Policy for this. The Policy name is EventPolicy.
When I try to use this policy and URL to connect to the service bus queue I get the following error:
40400: Endpoint Not Found
What am I doing wrong? Here is the code I am using:
// Uri to the Service Bus Queue
Uri uri = ServiceBusEnvironment.CreateServiceUri("sb", "ns-eventqueue", "EventQueue");
// Shared Access Signature (SAS) Authentication
string name = "EventPolicy";
string key = "TheKeyValue";
// Token Provider
TokenProvider tokenProvider = TokenProvider.CreateSharedAccessSignatureTokenProvider(name, key);
// Create a Messaging Factory
MessagingFactory factory = MessagingFactory.Create(uri, tokenProvider);
string filePath = #"C:\Temp\VTData\Ring Buffer.xml";
byte[] data = File.ReadAllBytes(filePath);
BrokeredMessage bm = new BrokeredMessage(data);
bm.Label = "Ring Buffer File";
try
{
MessageSender sender = factory.CreateMessageSender("EventQueue");
sender.Send(bm);
}
catch (Exception ex)
{
throw;
}
The issue was with the 3rd parameter of ServiceBusEnvironment.CreateServiceUri method. The third parameter was supposed to be blank.
I have code which inserts a blob into storage, and allows the user to view a list of the blobs, and an individual blob. However, I now can't get the blob to delete, the error that appears is
"An exception of type 'System.ServiceModel.FaultException`1' occurred in System.ServiceModel.ni.dll but was not handled in user code. Additional information: The remote server returned an error: (404) Not Found."
The code in the WCF service is
public void DeleteBlob(string guid, string uri)
{
//create the storage account with shared access key
CloudStorageAccount storageAccount = CloudStorageAccount.Parse(accountDetails);
CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
CloudBlobContainer container = blobClient.GetContainerReference(guid);
CloudBlockBlob blob = container.GetBlockBlobReference(uri);
blob.DeleteIfExists();
}
and then I access this in the mobile client application through SOAP services like:
private void mnuDelete_Click(object sender, EventArgs e)
{
MessageBoxResult message = MessageBox.Show("Are you sure you want to delete this image?", "Delete", MessageBoxButton.OKCancel);
if (message == MessageBoxResult.OK)
{
Service1Client svc = new Service1Client();
svc.DeleteBlobCompleted += new EventHandler<AsyncCompletedEventArgs>(svc_DeleteBlobCompleted);
svc.DeleteBlobAsync(container, uri);
}
}
void svc_DeleteBlobCompleted(object sender, AsyncCompletedEventArgs e)
{
if (e.Error == null) {
NavigationService.Navigate(new Uri("/Pages/albums.xaml", UriKind.Relative));
}
else {
MessageBox.Show("Unable to delete this photo at this time", "Error", MessageBoxButton.OK);
}
}
I also use SAS token to save the blob in the first place - I don't know whether this makes a difference?
In Azure Storage Client Library 4.0, we changed Get*Reference methods to accept relative addresses only. So, if you are using the latest library and the parameter "uri" is an absolute address, you should change it to either to the blob name or you should use the CloudBlockBlob constructor that takes an Uri and a StorageCredentials object.
Please see all such breaking changes in our GitHub repository.
I am using WindowsAzure.Storage (v8.1.4) in my ASP.NET Core MVC web app (v1.1.3).
I have an image crop and resize feature on my web app so I decide to use Azure Blob Storage to store the raw(user uploaded) pictures and the cropped (after resize) pictures.
One important thing to keep in mind even you're using the CloudBlockBlob constructor with the absolute uri is that you still need to pass your storage account credentials into CloudBlockBlob constructor.
public class AzureBlobStorageService : IBlobStorageService
{
private readonly AzureBlobConnectionConfigurations _azureBlobConnectionOptions;
private readonly CloudStorageAccount _storageAccount;
private readonly CloudBlobClient _blobClient;
public AzureBlobStorageService(IOptions<AzureBlobConnectionConfigurations> azureBlobConnectionAccessor)
{
_azureBlobConnectionOptions = azureBlobConnectionAccessor.Value;
_storageAccount = CloudStorageAccount.Parse(_azureBlobConnectionOptions.StorageConnectionString);
_blobClient = _storageAccount.CreateCloudBlobClient();
}
public async Task<Uri> UploadAsync(string containerName, string blobName, IFormFile image)
{
...
}
public async Task<Uri> UploadAsync(string containerName, string blobName, byte[] imageBytes)
{
...
}
public async Task<byte[]> GetBlobByUrlAsync(string url, bool deleteAfterFetch = false)
{
// This works
var blockBlob = new CloudBlockBlob(new Uri(url), _storageAccount.Credentials);
// Even this will fail
//var blockBlob = new CloudBlockBlob(new Uri(url));
await blockBlob.FetchAttributesAsync();
byte[] arr = new byte[blockBlob.Properties.Length];
await blockBlob.DownloadToByteArrayAsync(arr, 0);
if (deleteAfterFetch)
{
await blockBlob.DeleteIfExistsAsync();
}
return arr;
}
private async Task<CloudBlobContainer> CreateContainerIfNotExistAsync(string containerName)
{
var container = _blobClient.GetContainerReference(containerName);
if (!await container.ExistsAsync())
{
await container.CreateAsync();
await container.SetPermissionsAsync(new BlobContainerPermissions
{
PublicAccess = BlobContainerPublicAccessType.Blob
});
}
return container;
}
}
Hope this helps.
In Azure Storage Client Library 4.0, the get Reference method must be changed to accept relative addresses and nothing else . So, this does not support the libraries earlier than that,
you should change it to either to the blob name or you should use the CloudBlockBlob constructor that takes an Uri and a StorageCredentials object.
We are trying to know if a blob exists, so we are doing a FetchAttributes. It has worked well but in a load test, in thousand of requests, two of the requests failed in this method.
The error was BlobType of the blob reference doesn't match BlobType of the blob.
The blob exists.
Do you know if there is an error in the SDK 1.7 for this method?
This is the code, resumed. Thank you.
CloudStorageAccount cloudStorageAccount;
CloudStorageAccount.SetConfigurationSettingPublisher(
(configName, configSettingPublisher) => configSettingPublisher(serviceName));
cloudStorageAccount = CloudStorageAccount.Parse(
string.Format("DefaultEndpointsProtocol=https;AccountName={0};AccountKey={1}", accountName, accountKey));
BlobConnection blobConn =
new BlobConnection(GeneralConstants.GetValue(GeneralConstantsEnum.BlobPersistance), identity);
blobClient = this.Account.CreateCloudBlobClient();
blobContainer = blobClient.GetContainerReference(blobContainerName);
blobContainer.GetBlobReference(blobName);
CloudBlob blob = blobContainer.GetBlobReference(blobName);
blob.FetchAttributes(); //Throws the exception
operation = blob.Metadata["operation"];
productId = blob.Metadata["productId"];
clientId = blob.Metadata["clientId"];
workOrders = blob.DownloadText();