Как получить изображение из хранилища BLOB-объектов Azure через веб-интерфейс API в виде двоичного файла? - PullRequest
0 голосов
/ 17 октября 2019

У меня есть метод 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);
            }            
        }

Теперь мой вопрос касается конечной точкиПОЛУЧИТЬ. Поскольку изображение профиля должно отображаться на панели навигации в приложении, мне нужно получить его в двоичном формате, если это имеет смысл? Другими словами, я не могу вернуть URL-адрес ProfilePicture клиенту (приложению 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);
            }
        }

1 Ответ

1 голос
/ 17 октября 2019

Насколько я знаю, ваше React App покажет html-страницу, что означает, что в html будет html <img src="url">. Затем браузер попытается получить изображение из URL.

Итак, было бы 2 необязательных решения:

1.Создайте URL-адрес большого хранилища с помощью SAS и установите его в качестве URL-адреса изображения в <img>. С SAS клиника сможет получить доступ к изображению из хранилища напрямую.

2. URL-адресом будет путь запроса вашего Web API. Например: /image/{image_name}. И ваш веб-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");
    }
}

Снимок экрана:

enter image description here

...