Upload image to Azure blob with summernote - azure

public class StorageService
{
CloudStorageAccount storageAccount = CloudStorageAccount.Parse("DefaultEndpointsProtocol=removed for this post");
public async Task Upload(string id, Stream data)
{
CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
// Retrieve a reference to a container.
CloudBlobContainer container = blobClient.GetContainerReference("images");
await container.CreateIfNotExistsAsync();
container.SetPermissions(
new BlobContainerPermissions
{
PublicAccess = BlobContainerPublicAccessType.Blob
});
// Retrieve reference to a blob named "myblob".
CloudBlockBlob blockBlob = container.GetBlockBlobReference(id);
await blockBlob.UploadFromStreamAsync(data, data.Length);
}
public async Task UploadBlogPhoto(string id, Stream data)
{
CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
// Retrieve a reference to a container.
CloudBlobContainer container = blobClient.GetContainerReference("mycontainer");
await container.CreateIfNotExistsAsync();
container.SetPermissions(
new BlobContainerPermissions
{
PublicAccess = BlobContainerPublicAccessType.Blob
});
// Retrieve reference to a blob named "myblob".
CloudBlockBlob blockBlob = container.GetBlockBlobReference(id);
await blockBlob.UploadFromStreamAsync(data, data.Length);
}
}
So I have the StorageServices class and I use the first method, Upload, to upload users' profile pics.
here is the markup:
using (Html.BeginForm("UploadPhoto", "Manage", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<div class="browseimg">
<input type="file" class="display-none" name="file" id="files" onchange="this.form.submit()" />
</div>
}
<button class="btn btn-primary width-100p main-bg round-border-bot" id="falseFiles">
Upload billede
</button>
This is the summernote button for uploading a photo. The post uploads to a database. However, is there a way for the text to be uploaded to the database and the image to Azure blob? Would I need to do it asynchronously by first uploading the picture and adding the azure blob's URL into summernote, can it be done?

As Gaurav said, you could perform both operations in your upload functions. In my opinion, I recommend that you perform both operations in your upload action, in order to ensure data consistency. Here I provide you with a code sample to have a better understanding of it.
ManageController.cs
/// <summary>
/// Upload photo with description
/// </summary>
/// <param name="imageNote">description of the photo</param>
/// <returns></returns>
public async Task<JsonResult> UploadPhoto(string imageNote)
{
string operationResult = string.Empty;
string uploadedImageUrl = string.Empty;
uploadedImageUrl = await UploadImageToBlob();
//make sure the image is uploaded successfully to Azure Blob
if (!string.IsNullOrEmpty(uploadedImageUrl))
{
//insert the image(blob) Url and imageNote to your database
operationResult = "Operation is successful!";
}
else
operationResult = "Image upload failed, please check and submit again!";
return Json(new
{
Message = operationResult
});
}
/// <summary>
/// Upload photo to Azure Blob Storage
/// </summary>
/// <returns>the new Blob(photo) Url</returns>
private async Task<string> UploadImageToBlob()
{
string uploadedImageUrl = string.Empty;
try
{
var files = Request.Files;
if (files != null && files.Count > 0)
{
var file = files[0];
string blobName = Path.GetFileName(file.FileName);
#region upload image to Azure Blob and retrieve the Blob Url
CloudStorageAccount storageAccount = CloudStorageAccount.Parse(CloudConfigurationManager.GetSetting("brucechenStorage"));
CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
// Retrieve a reference to a container.
CloudBlobContainer container = blobClient.GetContainerReference("images");
await container.CreateIfNotExistsAsync();
// Retrieve reference to a blob named "blobName".
CloudBlockBlob blockBlob = container.GetBlockBlobReference(blobName);
await blockBlob.UploadFromStreamAsync(file.InputStream);
uploadedImageUrl = blockBlob.Uri.ToString();
#endregion
}
}
catch (Exception e)
{
//TODO:log
}
return uploadedImageUrl;
}

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

Why won't anything upload? - Uploading info blob to Azure with Xamarin

I have been trying for quite some time to get something to upload to my Azure blob container I have set up with an Xamarin.ios project.
I am not sure why it isn't working, and have explored many different options.
I get CS0426 whenever I try and refer to LimaBeans in my Viewcontroller.
Stumped.
This is my View Controller
using System;
using System.IO;
using UIKit;
namespace storingbuttondataaaa
{
public partial class ViewController : UIViewController
{
protected ViewController(IntPtr handle) : base(handle)
{
// Note: this .ctor should not contain any initialization logic.
}
public override void ViewDidLoad()
{
base.ViewDidLoad();
// Perform any additional setup after loading the view, typically from a nib.
}
public override void DidReceiveMemoryWarning()
{
base.DidReceiveMemoryWarning();
// Release any cached data, images, etc that aren't in use.
}
partial void FractureBtn_TouchUpInside(UIButton sender)
{
//get text box data
var name = FractureBtn;
string call = ("call 911, especially if blood is spraying everywhere!");
string line = string.Format("{0},{1}", name, call);
//Store the Information.
var documents = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
var filename = Path.Combine(documents, "HealthJournal.txt");
File.WriteAllText(filename, line);
;
}
partial void HandleAddClicked_TouchUpInside(UIButton sender)
{
activityIndicator.StartAnimating();
new BlobUpload.LimaBeans();
}
}
}
and this is my blob upload task:
using System;
using System.Diagnostics.Contracts;
using System.Threading.Tasks;
using Microsoft.WindowsAzure.Storage;
using Microsoft.WindowsAzure.Storage.Blob;
namespace storingbuttondataaaa
{
public class BlobUpload
{
public BlobUpload()
{
}
public static async Task LimaBeans(string localPath)
{
Contract.Ensures(Contract.Result<Task>() != null);
// Retrieve storage account from connection string.
CloudStorageAccount storageAccount = CloudStorageAccount.Parse("DefaultEndpointsProtocol=itsmypersonalkey");
// Create the blob client.
CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
// Retrieve reference to a previously created container.
CloudBlobContainer container = blobClient.GetContainerReference("submittedreqforbd");
// Create the container if it doesn't already exist.
await container.CreateIfNotExistsAsync();
// Retrieve reference to a blob named "myblob".
CloudBlockBlob blockBlob = container.GetBlockBlobReference("myblob");
//await blockBlob.UploadFromFileAsync(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments));
await blockBlob.UploadTextAsync("My Head Just Exploaded!");
}
}
}
What is wrong? I am on the verge of giving up!
No defining declaration found for implementing declaration of partial method ViewController.FractureBtn_TouchUpInside(UIButton)
We should define a declaration of this method in another partial class as below:
partial void FractureBtn_TouchUpInside(UIButton sender);
To upload local file to Azure, we can do as below:
/// <summary>
/// Upload file to Blob
/// </summary>
/// <param name="path">path of local file. For example: C:\Users\leel2\Desktop\333.txt</param>
/// <param name="blobName">For example: 333.txt</param>
/// <param name="containerName"></param>
public static void UploadBlob(string path, string blobName, string containerName)
{
CloudStorageAccount storageAccount = CloudStorageAccount.Parse("DefaultEndpointsProtocol=xxxxxxxx");
CloudBlobClient cloudBlobClient = storageAccount.CreateCloudBlobClient();
CloudBlobContainer container = cloudBlobClient.GetContainerReference(containerName);
container.CreateIfNotExists();
CloudBlockBlob blob = container.GetBlockBlobReference(blobName);
blob.UploadFromFile(path);
}

How to upload a file to a storage location through URL using Azure function app

I want to upload the upload a file to a storage location through URL using Azure function app from Azure blob storage. I'm able to pull the file from Azure blob. But not able to upload the file through url.
Below I have attached the code which i have written. Could anyone help me on this?
#r "Newtonsoft.Json"
#r "Microsoft.WindowsAzure.Storage"
#r "System.IO"
using System;
using System.IO;
using Microsoft.WindowsAzure.Storage;
using Microsoft.WindowsAzure.Storage.Blob;
using Microsoft.WindowsAzure.Storage.Auth;
using System.Xml;
using System.Collections.Generic;
using Newtonsoft.Json;
using System.Net;
public static void Run(string input, TraceWriter log)
{
log.Info($"C# manual trigger function processed\n");
const string StorageAccountName = "";
const string StorageAccountKey = "";
var storageAccount = new CloudStorageAccount(new StorageCredentials(StorageAccountName, StorageAccountKey), true);
var blobClient = storageAccount.CreateCloudBlobClient();
var container = blobClient.GetContainerReference("hannahtest");
var Destcontainer = blobClient.GetContainerReference("hannahtestoutput");
var blobs = container.ListBlobs();
log.Info($"Creating Client and Connecting");
foreach (IListBlobItem item in container.ListBlobs(null, false))
{
if (item is CloudBlockBlob blockBlob)
{
using (StreamReader reader = new StreamReader(blockBlob.OpenRead())
{
//old content string will read the blockblob (xml)till end
string oldContent1 = reader.ReadToEnd();
log.Info(oldContent1);
var content = new FormUrlEncodedContent(oldContent1);
var response = await client.PostAsync("http://www.example.com/recepticle.aspx", content);
var responseString = await response.Content.ReadAsStringAsync();
log.Info($"Success");
}
}
}
}
Have a look at Blob Output Binding - that's how the blobs are intended to be uploaded from Azure Functions, without messing with Azure Storage SDK.
Azure function to upload multiple image file to blob storage.
using Microsoft.WindowsAzure.Storage.Auth;
using Microsoft.WindowsAzure.Storage;
using Microsoft.WindowsAzure.Storage.Blob;
public static class ImageUploadFunction
{
[FunctionName("ImageUploadFunction")]
public static async Task<IActionResult> Run([HttpTrigger(AuthorizationLevel.Function, "post")]HttpRequestMessage req, ILogger log)
{
var provider = new MultipartMemoryStreamProvider();
await req.Content.ReadAsMultipartAsync(provider);
var files = provider.Contents;
List<string> uploadsurls = new List<string>();
foreach (var file in files) {
var fileInfo = file.Headers.ContentDisposition;
Guid guid = Guid.NewGuid();
string oldFileName = fileInfo.FileName;
string newFileName = guid.ToString();
var fileExtension = oldFileName.Split('.').Last().Replace("\"", "").Trim();
var fileData = await file.ReadAsByteArrayAsync();
try {
//Upload file to azure blob storage method
var upload = await UploadFileToStorage(fileData, newFileName + "." + fileExtension);
uploadsurls.Add(upload);
}
catch (Exception ex) {
log.LogError(ex.Message);
return new BadRequestObjectResult("Somthing went wrong.");
}
}
return uploadsurls != null
? (ActionResult)new OkObjectResult(uploadsurls)
: new BadRequestObjectResult("Somthing went wrong.");
}
private static async Task<string> UploadFileToStorage(byte[] fileStream, string fileName)
{
// Create storagecredentials object by reading the values from the configuration (appsettings.json)
StorageCredentials storageCredentials = new StorageCredentials("<AccountName>", "<KeyValue>");
// Create cloudstorage account by passing the storagecredentials
CloudStorageAccount storageAccount = new CloudStorageAccount(storageCredentials, true);
// Create the blob client.
CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
// Get reference to the blob container by passing the name by reading the value from the configuration (appsettings.json)
CloudBlobContainer container = blobClient.GetContainerReference("digital-material-library-images");
// Get the reference to the block blob from the container
CloudBlockBlob blockBlob = container.GetBlockBlobReference(fileName);
// Upload the file
await blockBlob.UploadFromByteArrayAsync(fileStream,0, fileStream.Length);
blockBlob.Properties.ContentType = "image/jpg";
await blockBlob.SetPropertiesAsync();
return blockBlob.Uri.ToString();
//return await Task.FromResult(true);
}
}

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 do I upload a file to Azure blob storage from a MVC view

I am coding a MVC5 internet application and would like some help to upload a file from my own filesystem to an Azure Blob.
Here is my Azure upload code function:
public void UploadFileToBlobStorage(string containerName, string blockBlogName, string fileName)
{
// Retrieve storage account from connection string.
CloudStorageAccount storageAccount = CloudStorageAccount.Parse(
CloudConfigurationManager.GetSetting("StorageConnectionString"));
// Create the blob client.
CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
// Retrieve reference to a previously created container.
CloudBlobContainer container = blobClient.GetContainerReference(containerName);
// Create the container if it doesn't already exist.
container.CreateIfNotExists();
container.SetPermissions(
new BlobContainerPermissions
{
PublicAccess =
BlobContainerPublicAccessType.Blob
});
// Retrieve reference to a blob named "myblob".
CloudBlockBlob blockBlob = container.GetBlockBlobReference(blockBlogName);
// Create or overwrite the "myblob" blob with contents from a local file.
using (var fileStream = System.IO.File.OpenRead(fileName))
{
blockBlob.UploadFromStream(fileStream);
}
}
Here is my function to upload a test file:
public void UploadTestFile(string localFileName)
{
string containerName = "TestContainer";
string blockBlogName = "Test.txt";
AzureService azureService = new AzureService();
azureService.UploadFileToBlobStorage(containerName, blockBlogName, localFileName);
}
I am not sure how to call the UploadTestFile() function from a MVC View where the user can browse to a file to upload.
Do I need to use Ajax, or can I simply upload a file by calling the method from a MVC view? Can I please have some help with this?
Thanks in advance
One way to call your UploadTestFile() function from an MVC View is by using the Html.BeginForm() method. I am including an example below:
#using (Html.BeginForm("UploadTestFile", "INSERT_YOUR_CONTROLLER_NAME_HERE", FormMethod.Post, new { enctype = "multipart/form-data" })) {
<span>
<input type="file" name="myFile" multiple /> <br>
<input type="submit" value="Upload" />
</span>
}
Also, a couple of suggestions on your code:
UploadFileToBlobStorage(): The code checks for container existence and setting permissions on every request. I would recommend separating the container.CreateIfNotExists() and container.SetPermissions(…) logic into a separate initialization function that needs to be executed only once on first deployment.
UploadFileToBlobStorage(): It looks like the code will try to upload the localFileName from the VM file system and not the multi-part form data. One approach would be to use the HttpFileCollectionBase class and the Controller.Request property. Example below:
public void UploadFileToBlobStorage(
string containerName,
string blockBlogName,
HttpFileCollectionBase files)
{
// .....
// Use this:
blockBlob.UploadFromStream(files[0].InputStream);
/* uploading the first file:
you can enumerate thru the files collection
if you are uploading multiple files */
/* Instead of this:
Create or overwrite the "myblob" blob with contents
from a local file. */
using (var fileStream = System.IO.File.OpenRead(fileName))
{
blockBlob.UploadFromStream(fileStream);
}
}
[HttpPost]
public void UploadTestFile()
{
string containerName = "TestContainer";
string blockBlogName = "Test.txt";
AzureService azureService = new AzureService();
// Notice the Request.Files instead of localFileName
azureService.UploadFileToBlobStorage(
containerName, blockBlogName, Request.Files);
}
Please let me know if that works on your end.

Resources