【问题标题】:How to I display an image from my Azure Blob Storage Account in my ASP.NET Core Application?如何在我的 ASP.NET Core 应用程序中显示来自 Azure Blob 存储帐户的图像?
【发布时间】:2020-07-14 06:33:35
【问题描述】:

我环顾四周,虽然我可以看到许多关于如何上传到 Azure Blob 存储的指南,但它们似乎都无法在您完成后检索您的数据。在我的场景中,我有一个应用程序,用户可以在创建图像时将图像上传到汽车,我为我的 blob 存储创建了一个服务,我将其用于依赖注入。

当用户尝试编辑汽车时,我希望他们能看到详细信息和相关图像。我正在努力返回该图像,我想我快到了,但不确定将我的信息返回为什么。

这是我从提交表单开始的代码。

创建

@model Car
<div class="row">
    <div class="col">
        <form asp-action="Create" asp-controller="Car" method="post" enctype="multipart/form-data">
            <div class="row">
                <div class="col">
                    <div class="md-form form-group">
                        <label asp-for="Name"></label>
                        <input type="text" class="form-control" asp-for="Name" />
                    </div>
                    <div class="md-form form-group">
                        <label asp-for="ImageFile" class="active">Image</label>
                        <!-- Image Upload-->
                        <kendo-upload name="ImageFile" show-file-list="true">
                        </kendo-upload>
                    </div>
                </div>
            </div>
            <div class="row">
                <div class="col">
                    <hr />
                    <button type="submit" class="btn btn-success">Submit</button>
                    <button type="reset" class="btn btn-amber">Reset</button>
                </div>
            </div>
        </form>
    </div>
</div>

以下是该 Create 视图的相应方法。正如您将看到的,我打开依赖注入,然后在方法中使用它。这仅用于上传 blob,一切正常,这是为了提供我的问题的完整上下文。

CarController.cs

private readonly ICarService _carService;
private readonly IWebHostEnvironment _env;
private readonly IConfiguration _configuration;

public CarController(
    IWebHostEnvironment env,
    ICarService carService,
    IConfiguration configuration)
{
    _carService = carService;
    _env = env;
    _configuration = configuration;
}
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Create(Car car)
{
    if (ModelState.IsValid)
    {
        //
        //Create Car First
        _carService.InsertCar(car);

        //
        //Get the id if the car just created            
        int id = car.Id;

        //
        //If file data is there, prepare and upload to
        //blob storage.
        if (car.ImageFile != null)
        {
            string category = "car";
            var fileName = "car-image.jpg";
            byte[] fileData = new byte[car.ImageFile.Length];
            string mimeType = car.ImageFile.ContentType;                   

            BlobStorageService objBlobService = new BlobStorageService(_configuration.GetConnectionString("AzureStorage"));

                car.ImagePath = objBlobService.UploadFileToBlob(
                    category, 
                    id, 
                    fileName, 
                    fileData, 
                    mimeType);
            }                
            return RedirectToAction(nameof(Index));
        }
        return View(car);
    }

下一部分是我苦苦挣扎的地方。我需要在编辑页面上显示上传的图像。这是我开始编写的方法,它不完整,从现在开始我需要帮助。

编辑

[HttpGet]
public IActionResult Edit(int id)
{
    //
    //Access the service and pass the car ID to it
    BlobStorageService objBlob = new BlobStorageService(_configuration.GetConnectionString("AzureStorage"));
        objBlob.GetBlobData(id.ToString());

    //
    //Get car data from the repository
    var data = _carService.GetCar(id);
    return View(data);
}

这是我的 blob 存储服务,它可以处理其中的大部分内容。正如您所看到的,当 ID 从编辑页面传递时,它用于在 Azure 上形成目录结构以查找相对图像。我正在返回属性,但这是不对的。

using Microsoft.WindowsAzure.Storage;
using Microsoft.WindowsAzure.Storage.Blob;
using System;
using System.IO;
using System.Threading.Tasks;
using Microsoft.Extensions.Configuration;

namespace MyProject.Services
{
    public class BlobStorageService
    {
        string accessKey = string.Empty;        

        public BlobStorageService(string endPoint)
        {
            accessKey = endPoint;
        }

        public string UploadFileToBlob(string category, int id, string strFileName, byte[] fileData, string fileMimeType)
        {
            try
            {
                var _task = Task.Run(() => this.UploadFileToBlobAsync(category, id, strFileName, fileData, fileMimeType));
                _task.Wait();
                string fileUrl = _task.Result;
                return fileUrl;
            }
            catch (Exception)
            {
                throw;
            }
        }

        public async void GetBlobData(string id)
        { 
            CloudStorageAccount cloudStorageAccount = CloudStorageAccount.Parse(accessKey);
            CloudBlobClient cloudBlobClient = cloudStorageAccount.CreateCloudBlobClient();

            string strContainerName = "uploads";
            CloudBlobContainer cloudBlobContainer = cloudBlobClient.GetContainerReference(strContainerName);

            string pathPrefix = "car/" + id;
            CloudBlobDirectory blobDirectory = cloudBlobContainer.GetDirectoryReference(pathPrefix);

            // get block blob reference  
            CloudBlockBlob blockBlob = blobDirectory.GetBlockBlobReference("car-image.jpg");

            await blockBlob.FetchAttributesAsync();
        }          

        private async Task<string> UploadFileToBlobAsync(string category, int id, string strFileName, byte[] fileData, string fileMimeType)
        {
            try
            {
                string strContainerName = "uploads";
                string fileName = category + "/" + id + "/" + strFileName;

                CloudStorageAccount cloudStorageAccount = CloudStorageAccount.Parse(accessKey);
                CloudBlobClient cloudBlobClient = cloudStorageAccount.CreateCloudBlobClient();                
                CloudBlobContainer cloudBlobContainer = cloudBlobClient.GetContainerReference(strContainerName);                

                if (await cloudBlobContainer.CreateIfNotExistsAsync().ConfigureAwait(false))
                {
                    await cloudBlobContainer.SetPermissionsAsync(new BlobContainerPermissions { PublicAccess = BlobContainerPublicAccessType.Blob }).ConfigureAwait(false);
                }

                if (fileName != null && fileData != null)
                {
                    CloudBlockBlob cloudBlockBlob = cloudBlobContainer.GetBlockBlobReference(fileName);
                    cloudBlockBlob.Properties.ContentType = fileMimeType;
                    await cloudBlockBlob.UploadFromByteArrayAsync(fileData, 0, fileData.Length).ConfigureAwait(false);
                    return cloudBlockBlob.Uri.AbsoluteUri;
                }
                return "";
            }
            catch (Exception ex)
            {
                throw (ex);
            }
        }
    }
}

所以,问题是,你如何返回图片的 URL,以便我可以将它放在 img src 标记中或下载它以显示?我让自己有点卡住了,不确定。虽然目录结构工作正常并且它找到了文件...我不知道如何使用它。

【问题讨论】:

  • blob 容器的 ACL 是私有的还是公有的?
  • 他们是公开的
  • 在这种情况下,请使用 Андрей Саяпин 提供的答案。基本上,在您的模型中,您应该有一个名为 image url 的属性,并且应该使用 blob 的 URL 进行填充,该 URL 的格式始终为:https://account.blob.core.windows.net/container/path/to/blob.extension

标签: c# azure asp.net-core azure-blob-storage


【解决方案1】:

From MS

简而言之:CloudBlockBlob 具有属性UriStorageUri。第一个直接指向文件,第二个允许选择主要或辅助网址。

如果允许匿名读取您的 blob(在 Azure 门户上配置)应该不会有任何问题

【讨论】:

    【解决方案2】:

    通常,您根本不返回 URL,而是返回一个巨大的字节块,内容类型为“image/jpeg”(或类似),这就是放入浏览器的内容。您的 img src 属性只需要引用返回这些字节的控制器操作。

    例如一个返回文件的控制器方法,而不使用 kestrel 内置的静态文件服务:

    [ResponseCache(Duration = 1200, Location = ResponseCacheLocation.Client)]
    public IActionResult GetImage(int id)
    {
        // determine file path from id and then
        return PhysicalFile(path, "image/jpeg");
    }
    

    现在您无法返回 PhysicalFile,但它只从磁盘读取字节并返回它们 - 对于任何文件都是一样的,只需更改内容类型。尝试一个 FileResult,复制返回的数据:

    return File(bytes, "image/jpeg", fileName);
    

    【讨论】:

    • 图像存储在 blob 存储中,而不是服务器本身。不确定您的解决方案将如何工作。
    • @GauravMantri 通过获取组成图像的字节,就像他已经做的那样,然后在内存中创建的 File 对象中返回它。
    • 所以这应该是另一个actionresult因此我们可以用ajax请求显示在cshtml文件上??
    猜你喜欢
    • 2020-07-18
    • 2020-07-18
    • 2021-08-23
    • 2017-05-16
    • 2020-06-22
    • 1970-01-01
    • 2017-11-08
    • 2016-03-28
    • 1970-01-01
    相关资源
    最近更新 更多