Хранилище больших двоичных объектов Azure — ошибка отображения загруженных изображений

#azure #.net-core #blob #azure-blob-storage

Вопрос:

Я перепробовал множество различных подходов и прочитал множество ответов на этот вопрос, но, обратившись за помощью в этом, я наткнулся на стену.

У меня есть учетная запись хранения и контейнер в azure, я успешно загружаю туда изображения, но по какой-то причине они кажутся повреждающими.

Я не могу получить доступ к изображениям с помощью тега img и не могу их просматривать (в фотографиях Windows), если загружаю их непосредственно из контейнера.

Я считаю, что у меня правильная конфигурация, большой двоичный объект уровня общего доступа (я также пробовал контейнер уровня общего доступа).

уровень доступа к контейнеру
уровень доступа img

просмотр загруженного большого двоичного объекта
большой двоичный объект azure img

Изображение не отображается по URL-адресу на моей странице razor

html-тег img
отсутствует страница img razor

Я также не смогу просмотреть его, если скачаю и открою в Windows

загруженный img из контейнера
поврежденное изображение

2 примера подходов к потоку файлов, которые я попробовал ниже

     //approach 1   
     
    
        using (FileStream fileStream = new FileStream(filePath, FileMode.Open))
                    {
                        BlobClient blobClient = container.GetBlobClient(fileName);
                        await blobClient.UploadAsync(fileStream, new BlobHttpHeaders { ContentType = "image/jpg" });
                    }
    
    //approach 2
    
            using (FileStream fileStream = new FileStream(filePath, FileMode.Open))
            {
                container.UploadBlob(attachment.FileName, fileStream);
            }
    
//service
    public async Task<bool> UploadSample(IFormFile attachment)
            {
                var configSection = Configuration.GetSection("AzureBlobStorge");
                var connectionString = configSection.GetSection("ConnectionString").Value;
                var containerName = configSection.GetSection("ContainerName").Value;
    
                string fileName = Path.GetFileName(attachment.FileName);
                string filePath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot\images\profiles", fileName);
    
                BlobContainerClient container = new BlobContainerClient(connectionString, containerName);
    
                container.SetAccessPolicy(PublicAccessType.BlobContainer);
    
                using (FileStream fileStream = new FileStream(filePath, FileMode.Open))
                {
                    container.UploadBlob(attachment.FileName, fileStream);
    
                    //BlobClient blobClient = container.GetBlobClient(fileName);
                    //await blobClient.UploadAsync(fileStream, new BlobHttpHeaders { ContentType = "image/jpg" });
                }
                return true;
            }

//controller
        [HttpPost]
        [ActionName("ProfilePicsAsync")]
        [ValidateAntiForgeryToken]
        public async Task<ActionResult> ProfilePicsAsync(Members item)
        {
            try
            {
                IFormFile formFile = HttpContext.Request.Form.Files[0];
                var member = await _cosmosDbService.GetItemAsync(formFile.Name); //Id passed in the formfile object under name
                if (ModelState.IsValid)
                {
                    if (IsAdminUser())
                    {
                        if (formFile != null)
                        {
                            await _blobStorageService.UploadSample(formFile);
                        }
                        return RedirectToAction("Index");
                    }
                    return BadRequest("Not Authorised");
                }
            }
            catch (Exception ex)
            {
                if(ex is BusinessRuleException)
                {
                    return BadRequest(new BusinessRuleException(ex.Message));
                }
            }

//view
<form asp-action="ProfilePicsAsync" asp-controller="Home" method="post" enctype="multipart/form-data">
    @Html.HiddenFor(m => m.Id)
    <p>INPUT</p>
    <input asp-for="Attachment" Name="@Model.Id" />
    <button type="submit" id="btnUpload" class="btn btn-primary">Upload</button>
</form>
 

Комментарии:

1. Вы загружаете его с неправильным типом контента.

2. Я полагаю, что проблема связана с вашим процессом загрузки. Можете ли вы поделиться кодом для загрузки изображения?

3. Я обновил свой пост кодом загрузки, заранее спасибо

Ответ №1:

Как упоминалось в комментариях, проблема действительно связана с вашим кодом загрузки. По сути, вы загружаете файл с нулевым байтом. Это происходит из-за следующей строки кода:

 using (FileStream fileStream = new FileStream(filePath, FileMode.Create))
 

При использовании FileMode.Create , если файл существует, он будет перезаписан. Из документации here :

Указывает, что операционная система должна создать новый файл. Если файл уже существует, он будет перезаписан. Для этого требуется разрешение на запись. Файловый режим.Создать эквивалентно запросу о том, чтобы, если файл не существует, использовать CreateNew; в противном случае используйте Усечение. Если файл уже существует, но является скрытым файлом, возникает исключение UnauthorizedAccessException.

Таким образом, по сути, вы перезаписываете файл, который хотите загрузить, файлом с нулевым байтом, а затем загружаете этот файл с нулевым байтом.

Чтобы исправить это, пожалуйста, измените приведенную выше строку кода на:

 using (FileStream fileStream = new FileStream(filePath, FileMode.Open))
 

После этого и ваша загрузка, и загрузка должны работать.

Комментарии:

1. Спасибо Гуарав, это имело смысл, и я был очень взволнован, однако это не решило проблему. Я собираюсь опубликовать больше своего кода в вопросе на случай, если что-то еще покажется неправильным. Я действительно ценю то время, которое вы потратили на то, чтобы ответить до сих пор.

2. С какими проблемами вы сталкиваетесь в своем обновленном коде?

3. Что-то действительно странное произошло после того, как я внес предложенное вами изменение на самом деле, похоже, оно сохраняется в виде какого-то аудиофайла, когда я открыл его, я мог слышать разговоры людей. Просто сделало все это еще более странным! docs.microsoft.com/en-us/azure/storage/blobs/… Я думаю, что мог бы попробовать этот учебник и посмотреть, как выглядит код, сгенерированный командами CLI

4. Таким образом, вы загружаете файл изображения, однако загружается другой файл. Это правда? Можете ли вы сравнить загружаемый локальный файл с загружаемым файлом? Являются ли они оба одинаковыми?

5. github.com/Azure-Samples/storage-blob-upload-from-webapp Контроллер изображений в этом уроке в основном имел для меня рабочее решение, я выбросил большую часть своего кода и начал снова. Еще раз спасибо за помощь 🙂

Ответ №2:

Учебное пособие: https://docs.microsoft.com/en-us/azure/storage/blobs/storage-upload-process-images?tabs=dotnet,azure-powershell

Репо: https://github.com/Azure-Samples/storage-blob-upload-from-webapp

Контроллер изображений в этом уроке в основном имел для меня рабочее решение, я выбросил большую часть своего кода и начал снова.

Это было самое важное

 if (StorageHelper.IsImage(formFile))
{
    if (formFile.Length > 0)
    {
        using (Stream stream = formFile.OpenReadStream())
        {
            isUploaded = await StorageHelper.UploadFileToStorage(stream, formFile.FileName, storageConfig);
        }
    }
}