I'm currently able to upload and display an image from my blob storage but i'm struggling to find a way to 'update/replace' that image if a user would like to change it. I'm happy with either of two methods:
- Replace the image and keep the same url
- Upload a new image and reference a new url in the database
In the controller i'm using Dependency Injection for the photoService:
MANAGE CONTROLLER
//
// GET: /Manage/Index
public async Task<ActionResult> Index(ManageMessageId? message)
{
ViewBag.StatusMessage =
message == ManageMessageId.ChangePasswordSuccess ? "Your password has been changed."
: message == ManageMessageId.SetPasswordSuccess ? "Your password has been set."
: message == ManageMessageId.SetTwoFactorSuccess ? "Your two-factor authentication provider has been set."
: message == ManageMessageId.Error ? "An error has occurred."
: message == ManageMessageId.AddPhoneSuccess ? "Your phone number was added."
: message == ManageMessageId.RemovePhoneSuccess ? "Your phone number was removed."
: "";
var userId = User.Identity.GetUserId();
var model = new IndexViewModel
{
HasPassword = HasPassword(),
PhoneNumber = await UserManager.GetPhoneNumberAsync(userId),
TwoFactor = await UserManager.GetTwoFactorEnabledAsync(userId),
Logins = await UserManager.GetLoginsAsync(userId),
BrowserRemembered = await AuthenticationManager.TwoFactorBrowserRememberedAsync(userId)
};
// PhotoService
var user = new ApplicationUser
{
PhotoUrl = await _photoService.UploadPhotoAsync(model.Photo)
};
await UserManager.CreateAsync(user);
// PhotoService END
return View(model);
}
SERVICE
public class PhotoService : IPhotoService
{
public async void CreateAndConfigureAsync()
{
try
{
CloudStorageAccount storageAccount = StorageUtils.StorageAccount;
// Create a blob client and retrieve reference to images container
CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
CloudBlobContainer container = blobClient.GetContainerReference("images");
// Create the "images" container if it doesn't already exist.
if (await container.CreateIfNotExistsAsync())
{
// Enable public access on the newly created "images" container
await container.SetPermissionsAsync(
new BlobContainerPermissions
{
PublicAccess =
BlobContainerPublicAccessType.Blob
});
// Logging
}
}
catch (Exception ex)
{
// Logging
}
}
public async Task<string> UploadPhotoAsync(HttpPostedFileBase photoToUpload)
{
if (photoToUpload == null || photoToUpload.ContentLength == 0)
{
return null;
}
string fullPath = null;
Stopwatch timespan = Stopwatch.StartNew();
try
{
CloudStorageAccount storageAccount = StorageUtils.StorageAccount;
// Create the blob client and reference the container
CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
CloudBlobContainer container = blobClient.GetContainerReference("images");
// Create a unique name for the images we are about to upload
string imageName = String.Format("task-photo-{0}{1}",
Guid.NewGuid().ToString(),
Path.GetExtension(photoToUpload.FileName));
// Upload image to Blob Storage
CloudBlockBlob blockBlob = container.GetBlockBlobReference(imageName);
blockBlob.Properties.ContentType = photoToUpload.ContentType;
await blockBlob.UploadFromStreamAsync(photoToUpload.InputStream);
// Convert to be HTTP based URI (default storage path is HTTPS)
var uriBuilder = new UriBuilder(blockBlob.Uri);
uriBuilder.Scheme = "http";
fullPath = uriBuilder.ToString();
timespan.Stop();
//log.TraceApi("Blob Service", "PhotoService.UploadPhoto", timespan.Elapsed, "imagepath={0}", fullPath);
}
catch (Exception ex)
{
//log.Error(ex, "Error upload photo blob to storage");
}
return fullPath;
}
}
INTERFACE
public interface IPhotoService
{
void CreateAndConfigureAsync();
Task<string> UploadPhotoAsync(HttpPostedFileBase photoToUpload);
}
MODEL
public class IndexViewModel
{
public bool HasPassword { get; set; }
public IList<UserLoginInfo> Logins { get; set; }
public string PhoneNumber { get; set; }
public bool TwoFactor { get; set; }
public bool BrowserRemembered { get; set; }
public HttpPostedFileBase Photo { get; set; }
public string PhotoUrl { get; set; }
}
VIEW
@using Microsoft.AspNet.Identity
@model AzureBlobStorageTest.Models.IndexViewModel
@{
ViewBag.Title = "Manage";
}
<h2>@ViewBag.Title.</h2>
<p class="text-success">@ViewBag.StatusMessage</p>
<div>
<h4>Change your account settings</h4>
<h5>Image:</h5>
<img src="@(Model.PhotoUrl)" alt="Photo"/>
@using (Html.BeginForm("Index", "Manage", FormMethod.Post, new { role = "form", enctype = "multipart/form-data" }))
{
@Html.AntiForgeryToken()
@Html.ValidationSummary("", new { @class = "text-danger" })
<div class="form-group">
@Html.LabelFor(m => m.Photo, new { @class = "col-md-2 control-label" })
<div class="col-md-10">
@Html.TextBoxFor(m => m.Photo, new { type = "file" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" class="btn btn-default" value="Register" />
</div>
</div>
}
</div>
It would be great if someone could help me with this as I've been trying all sorts of ways but having no luck.
Please let me know if you require any further info.
Thanks
await blockBlob.UploadFromStreamAsync(photoToUpload.InputStream);will overwrite the existing file if it exists so it should work without doing anything