使用ASP.NET身份在Azure Blob存储中更新图像



我当前能够上传并显示blob存储中的图像,但是如果用户想更改,我正在努力寻找一种方法来'更新/替换'该图像它。我对两种方法之一感到满意:

  1. 更换图像并保留相同的URL
  2. 上传新图像并在数据库中引用新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
}

相关内容

  • 没有找到相关文章