Image upload to Azure - c#

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();
}

Related

Filestream a blob from Azure storage

I have images in Azure that I need to add in a pdf using pdfJet.
This is the code that I use if I read an image on disk, however I have a lot of images and it does not make sense to download them from Azure.
Image image = new Image(objects, new BufferedStream(new FileStream(LocalPath + "image.PNG", FileMode.Open, FileAccess.Read)), ImageType.PNG);
PS: This is done in asp.net webforms.
Thank you for your help.
I am now using the following function to read a PDF:
public MemoryStream DownloadToMemoryStream(DTO.BlobUpload b)
{
CloudStorageAccount storageAccount = Conn.SNString(b.OrgID);
CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
CloudBlobContainer container = blobClient.GetContainerReference(b.Container);
CloudBlockBlob blob = container.GetBlockBlobReference(b.FileName);
var sasToken = blob.GetSharedAccessSignature(new SharedAccessBlobPolicy()
{
Permissions = SharedAccessBlobPermissions.Read,
SharedAccessExpiryTime = DateTime.UtcNow.AddMinutes(10),//assuming the blob can be downloaded in 10 miinutes
}, new SharedAccessBlobHeaders()
{
ContentDisposition = "attachment; filename=file-name"
});
using (MemoryStream ms = new MemoryStream())
{
blob.DownloadToStream(ms);
return ms;
}
}
And in the aspx page I use:
MemoryStream pdfScript = B.DownloadToMemoryStream(b);
to read the stream:
SortedDictionary<Int32, PDFobj> objects = pdfFinalScript.Read(pdfScript);
However I get the error message:
Cannot access a closed Stream
I have looked at how to open the stream but haven't managed to do it.
Could you please help, thank you
According to your description, you would download blobs from Azure.
Here are several ways you could refer to.
1.Download with blob url.
Create a Shared Access Signature with Read permission and Content-Disposition header set and create blob URL based on that and use that URL. In this case, the blob contents will be directly streamed from storage to the client browser.
2.Get the blob and DownloadFileFromBlob.
3.Download file to exactly path in local.
Webform:
You could use Response.Redirect(blobUrl); to redirect blob url and download it.
In .aspx:
<asp:Button ID="Button1" runat="server" Text="Click Me" OnClick="Button1_Click" />
In aspx.cs:
protected void Button1_Click(object sender, EventArgs e)
{
CloudStorageAccount account = new CloudStorageAccount(new StorageCredentials("accountname", "accountkey"), true);
var blobClient = account.CreateCloudBlobClient();
var container = blobClient.GetContainerReference("container");
var blob = container.GetBlockBlobReference("text.PNG");
var sasToken = blob.GetSharedAccessSignature(new SharedAccessBlobPolicy()
{
Permissions = SharedAccessBlobPermissions.Read,
SharedAccessExpiryTime = DateTime.UtcNow.AddMinutes(10),//assuming the blob can be downloaded in 10 miinutes
}, new SharedAccessBlobHeaders()
{
ContentDisposition = "attachment; filename=file-name"
});
using (MemoryStream ms = new MemoryStream())
{
blob.DownloadToStream(ms);
Image image = new Image(objects, ms, ImageType.PNG);
}
}

upload media to azure blob storage using asp.net web api 2

I'm developing rest web api that uploads images to my azure blob, I used one of the online tutorial and got this code
public class DocumentsController : ApiController
{
private const string CONTAINER = "documents";
// POST api/<controller>
public async Task<HttpResponseMessage> Post()
{
var context = new StorageContext();
// Check if the request contains multipart/form-data.
if (!Request.Content.IsMimeMultipartContent())
{
throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
}
// Get and create the container
var blobContainer = context.BlobClient.GetContainerReference(CONTAINER);
blobContainer.CreateIfNotExists();
string root = HttpContext.Current.Server.MapPath("~/App_Data");
var provider = new MultipartFormDataStreamProvider(root);
try
{
// Read the form data and return an async task.
await Request.Content.ReadAsMultipartAsync(provider);
// This illustrates how to get the file names for uploaded files.
foreach (var fileData in provider.FileData)
{
var filename = fileData.LocalFileName;
var blob = blobContainer.GetBlockBlobReference(filename);
using (var filestream = File.OpenRead(fileData.LocalFileName))
{
blob.UploadFromStream(filestream);
}
File.Delete(fileData.LocalFileName);
}
return Request.CreateResponse(HttpStatusCode.OK);
}
catch (System.Exception e)
{
return Request.CreateErrorResponse(HttpStatusCode.InternalServerError, e);
}
}
it is uploading the image in my account blob container but when i open azure storage manager and access the container i get wrong format as below picture describes
enter image description here
can u see the content-type ? I'm not able open this path in explorer
any help would be appreciated
Is your "filename" from code below have extension included when you debuging (like .jpg, .png)? For example "image.jpg"
var blob = blobContainer.GetBlockBlobReference(filename);
Also "fileData.LocalFileName" from code below need to have file extension
using (var filestream = File.OpenRead(fileData.LocalFileName))
It doesn't have extension and for this reason you have such issue

Uploading Base64 Image to Azure Blob

I have the following ASPX markup:
<asp:Image ImageUrl="placeholder.png" runat="server" ID="plhdr" />
The webpage lets a user upload an image, which is processed through a JavaScript library and then set as the source of the above control. The JavaScript sets the source as a Base64 String like this:
data:image/jpeg;base64,/9j/4AAQ...
I have a function on the same page that is meant to upload the displayed image to Azure Storage and then add a reference to it in Azure SQL. The code I have in the code behind is:
StorageCredentials creden = new StorageCredentials(accountname, accesskey);
CloudStorageAccount acc = new CloudStorageAccount(creden, useHttps: true);
CloudBlobClient client = acc.CreateCloudBlobClient();
CloudBlobContainer cont = client.GetContainerReference("testcont");
cont.CreateIfNotExists();
cont.SetPermissions(new BlobContainerPermissions
{
PublicAccess = BlobContainerPublicAccessType.Blob
});
CloudBlockBlob cblob = cont.GetBlockBlobReference("cblob");
var imagesrc = plhdr.ImageUrl;
cblob.UploadFromFile(#imagesrc);
var imageUrl = cblob.Uri;
Server Error in '/' Application. Could not find a part of the path
'D:\Windows\system32\placeholder.png'. Exception Details:
System.IO.DirectoryNotFoundException: Could not find a part of the
path 'D:\Windows\system32\dist\img\fling\space.gif'.
At this line: cblob.UploadFromFile(#imagesrc);.
Hoping someone can point me in the right direction.
According to your description, we can upload the image file to azure storage by using UploadFromStream(stream), Please have a try to do it with following sample code. It works for me.
CloudBlockBlob cblob = cont.GetBlockBlobReference("testblob");
var bytes = Convert.FromBase64String(#"iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==");// without data:image/jpeg;base64 prefix, just base64 string
using (var stream = new MemoryStream(bytes))
{
cblob.UploadFromStream(stream);
}

Azure Storage Client Library Upload with Proxy server

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

Delete a blob from Windows azure in c#

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.

Categories