【问题标题】:How to get an image from Azure Blob Storage via web api as binary?如何通过 web api 从 Azure Blob 存储中获取图像作为二进制文件?
【发布时间】:2020-02-14 00:33:35
【问题描述】:

我有一个 webapi 方法,以便用户可以上传他们自己的个人资料图片,但是在我保存在 CosmosDB 中的实体中,我保存了个人资料图片 URL。

  public async Task<IHttpActionResult> UpdateSuperAdministrator(SuperAdministrator superadministrator)
        {
            var telemetry = new TelemetryClient();
            try
            {
                var superAdministratorStore = CosmosStoreHolder.Instance.CosmosStoreSuperAdministrator;
                //First we validate the model
                if (!ModelState.IsValid)
                {
                    return BadRequest(ModelState);
                }

                //Then we validate the content type
                if (!Request.Content.IsMimeMultipartContent("form-data"))
                {
                    throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
                }

                //Initalize configuration settings
                var accountName = ConfigurationManager.AppSettings["storage:account:name"];
                var accountKey = ConfigurationManager.AppSettings["storage:account:key"];
                var profilepicturecontainername = ConfigurationManager.AppSettings["storage:account:profilepicscontainername"];

                //Instance objects needed to store the files
                var storageAccount = new CloudStorageAccount(new StorageCredentials(accountName, accountKey), true);
                CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
                CloudBlobContainer imagesContainer = blobClient.GetContainerReference(profilepicturecontainername);
                var provider = new AzureStorageMultipartFormDataStreamProvider(imagesContainer);

                foreach (MultipartFileData file in provider.FileData)
                {

                    var fileName = file.Headers.ContentDisposition.FileName.Trim('\"').Trim();
                    if (fileName.EndsWith(".png"))
                    {
                        var img = Image.FromFile(file.LocalFileName);
                        if (img.Width != 200 && img.Height != 200)
                        {
                            string guid = Guid.NewGuid().ToString();

                            return BadRequest($"Error Lulo. Unsupported extension, only PNG is valid. Or unsuported image dimensions (200px x 200px)");
                        }
                    }
                }

                //Try to upload file
                try
                {
                    await Request.Content.ReadAsMultipartAsync(provider);
                }
                catch (Exception ex)
                {
                    string guid = Guid.NewGuid().ToString();
                    var dt = new Dictionary<string, string>
                    {
                        { "Error Lulo: ", guid }
                    };
                    telemetry.TrackException(ex, dt);
                    return BadRequest($"Error Lulo. An error has occured. Details: {guid} {ex.Message}: ");
                }

                // Retrieve the filename of the file you have uploaded
                var filename = provider.FileData.FirstOrDefault()?.LocalFileName;
                if (string.IsNullOrEmpty(filename))
                {
                    string guid = Guid.NewGuid().ToString();
                    var dt = new Dictionary<string, string>
                    {
                        { "Error Lulo: ", guid }
                    };

                    return BadRequest($"Error Lulo. An error has occured while uploading your file. Please try again.: {guid} ");
                }

                //Rename file
                CloudBlockBlob blobCopy = imagesContainer.GetBlockBlobReference(superadministrator.Id + ".png");
                if (!await blobCopy.ExistsAsync())
                {
                    CloudBlockBlob blob = imagesContainer.GetBlockBlobReference(filename);

                    if (await blob.ExistsAsync())
                    {
                        await blobCopy.StartCopyAsync(blob);
                        await blob.DeleteIfExistsAsync();
                    }
                }

                superadministrator.ProfilePictureUrl = blobCopy.Name;

                var result = await superAdministratorStore.UpdateAsync(superadministrator);
                return Ok(result);
            }
            catch (Exception ex)
            {
                string guid = Guid.NewGuid().ToString();
                var dt = new Dictionary<string, string>
                {
                    { "Error Lulo: ", guid }
                };

                telemetry.TrackException(ex, dt);
                return BadRequest("Error Lulo: " + guid);
            }            
        }

现在我的问题是关于端点 GET。因为头像需要显示在应用程序的导航栏中,所以我需要以二进制格式获取它,如果这样有意义吗? 换句话说,我无法将 ProfilePicture URL 返回给客户端(一个 React 应用程序),因为它是一个无法访问 blob 存储的客户端应用程序。

这是我的收获。

[HttpGet]
        public async Task<IHttpActionResult> GetSuperAdministrator(string email)
        {
            var telemetry = new TelemetryClient();
            try
            {
                var superAdministratorStore = CosmosStoreHolder.Instance.CosmosStoreSuperAdministrator;

                var superadministrator = await superAdministratorStore.Query().FirstOrDefaultAsync(x => x.EmailAddress == email);
                if (superadministrator == null)
                {
                    return NotFound();
                }

                return Ok(superadministrator);
            }
            catch (Exception ex)
            {
                string guid = Guid.NewGuid().ToString();
                var dt = new Dictionary<string, string>
                {
                    { "Error Lulo: ", guid }
                };

                telemetry.TrackException(ex, dt);
                return BadRequest("Error Lulo: " + guid);
            }
        }

【问题讨论】:

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


    【解决方案1】:

    据我所知,你的 React App 会显示一个 html 页面,这意味着 html 中会有一个 html &lt;img src="url"&gt;。然后浏览器将尝试从 url 获取图像。

    因此,将有 2 个可选解决方案:

    1.使用SAS生成一个存储blob url,并将其设置为&lt;img&gt;中的图像url。使用 SAS,客户端将能够直接从存储中访问图像。

    2. url 是你的 Web API 的请求路径。例如:/image/{image_name}。你的 web api 会返回一张图片:

    [HttpGet]
    public IActionResult GetImage()
    {           
        // Get the image blob
        CloudBlockBlob cloudBlockBlob = ********;
        using(MemoryStream ms = new MemoryStream())
        {
            cloudBlockBlob.DownloadToStream(ms);
            return File(ms.ToArray(), "image/jpeg");
        }
    }
    

    更新:

    我的代码:

    public IActionResult Index()
    {
        string connString = "DefaultEndpointsProtocol=https;AccountName=storagetest789;AccountKey=G36mcmEthM****=;EndpointSuffix=core.windows.net";
        CloudStorageAccount storageAccount = CloudStorageAccount.Parse(connString);
        CloudBlobClient cloudBlobClient = storageAccount.CreateCloudBlobClient();
    
        CloudBlobContainer cloudBlobContainer = cloudBlobClient.GetContainerReference("pub");
        CloudBlockBlob cloudBlockBlob = cloudBlobContainer.GetBlockBlobReference("p033tw9j.jpg");
    
        using (MemoryStream ms = new MemoryStream())
        {
            cloudBlockBlob.DownloadToStream(ms);
            return File(ms.ToArray(), "image/jpeg");
        }
    }
    

    截图:

    【讨论】:

    • 你确定最后一行吗?我明白了。错误 CS1955 不可调用的成员“文件”不能像方法一样使用。
    • 对不起,我刚刚在一个 web 应用程序项目中进行了测试。 Controller 类中有一个 File 方法。当您使用 web api 时,您需要 return new FileContentResult(....)
    猜你喜欢
    • 2021-01-30
    • 2020-10-23
    • 2020-02-29
    • 2021-11-01
    • 1970-01-01
    • 2023-01-16
    • 2021-01-17
    • 2021-04-24
    • 2020-03-02
    相关资源
    最近更新 更多