使用asp.net Identity在Azure Blob存储中更新映像

问题描述 投票:0回答:1

我目前能够从我的blob存储器上传和显示图像,但是如果用户想要更改它,我很难找到“更新/替换”该图像的方法。我对两种方法中的任何一种都很满意:

  1. 替换图像并保持相同的URL
  2. 上传新图像并在数据库中引用新URL

在控制器中我使用依赖注入为photoService:

管理控制器

//
    // 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>

如果有人可以帮助我,那将是很好的,因为我一直在尝试各种各样的方法,但没有运气。

如果您需要任何进一步的信息,请告诉我。

谢谢

asp.net azure asp.net-identity azure-storage-blobs
1个回答
1
投票

正如Thomas所述,CloudBlockBlob.UploadFromStreamAsync会将流上传到块blob,如果blob已经存在,它将被覆盖。但是你的blob名称在UploadPhotoAsync方法下是唯一的,如下所示:

string imageName = String.Format("task-photo-{0}{1}",
            Guid.NewGuid().ToString(),
            Path.GetExtension(photoToUpload.FileName));

我建议您在DeletePhotoAsync下定义一个新方法(例如IPhotoService),然后检索现有图像,然后在调用UploadPhotoAsync方法上传新图像之前将其删除。

或者你可以为photoUrl方法添加一个可选参数名称UploadPhotoAsync,如果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
}
© www.soinside.com 2019 - 2024. All rights reserved.