我当前能够上传并显示blob存储中的图像,但是如果用户想更改,我正在努力寻找一种方法来'更新/替换'该图像它。我对两种方法之一感到满意:
- 更换图像并保留相同的URL
- 上传新图像并在数据库中引用新URL
在控制器中,我使用的是依赖性注入照片服务:
管理控制器
//
// 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);
}
服务
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;
}
}
接口
public interface IPhotoService
{
void CreateAndConfigureAsync();
Task<string> UploadPhotoAsync(HttpPostedFileBase photoToUpload);
}
模型
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; }
}
查看
@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>
如果我一直在尝试各种方式,但是没有运气,那将是很棒的。
如果您需要任何其他信息,请告诉我。
谢谢
正如托马斯(Thomas)评论说,cloudblockblob.uploadfromstreamasync会将流上传到块斑点上,如果已经存在斑点,它将被覆盖。但是您的斑点名称在UploadPhotoAsync
方法下是唯一的,如下所示:
string imageName = String.Format("task-photo-{0}{1}",
Guid.NewGuid().ToString(),
Path.GetExtension(photoToUpload.FileName));
我建议您在IPhotoService
下定义一种新方法(例如DeletePhotoAsync
),然后检索现有图像,然后在调用UploadPhotoAsync
方法上删除它以上载新图像。
或者您可以为UploadPhotoAsync
方法添加可选的参数名称photoUrl
,如果photoUrl
不是null或空的,则可以按以下方式初始化imageName
初始化:
imageName = new CloudBlockBlob(new Uri($"{photoUrl}")).Name;
更新:
您的PhotoService
看起来像这样:
public class PhotoService:IPhotoService
{
CloudBlobContainer container;
public PhotoService()
{
CloudStorageAccount storageAccount = StorageUtils.StorageAccount;
// Create a blob client and retrieve reference to images container
CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
container= blobClient.GetContainerReference("images");
}
//photoUrl: https://<account-name>.blob.core.windows.net/images/task-photo-09e0e292-8df2-4630-81a5-cb4977eef1f9.png
public async Task<bool> DeletePhotoAsync(string photoUrl)
{
string blobName = new CloudBlockBlob(new Uri(photoUrl)).Name;
var targetBlob = container.GetBlockBlobReference(blobName);
return await targetBlob.DeleteIfExistsAsync();
}
public async void CreateAndConfigureAsync()
{
try
{
// 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
}
}
//UploadPhotoAsync
}