Почему мои загруженные изображения на Azure содержат ошибки, препятствующие их отображению? - PullRequest
0 голосов
/ 02 апреля 2020

Я загрузил изображения в свою учетную запись хранения BLOB-файлов в Azure, всякий раз, когда я пытаюсь получить доступ к этим изображениям либо через веб-браузер, либо через обозреватель контейнеров azure, я получаю сообщение об ошибке

Изображение "what.jpg" не может быть отображено, потому что оно содержит ошибки.

Это не дает мне больше информации, чем это, глядя на файл в проводнике Azure Я вижу, что он был назван правильно, имеет правильный тип изображения, имеет данные, как я могу видеть байты.

Я посмотрел на права доступа, и я установил папку контейнера на publi c read access как не требующий ключ. Чтобы дополнительно проверить ошибки, я загрузил те же изображения через панель управления azure непосредственно в учетную запись хранения, и они работают, поэтому проблема должна заключаться в том, как я их загрузил.

Ради В этом контексте я использую службу хранения больших двоичных объектов в своем приложении с внедрением зависимостей для использования в моем контроллере.

Создать

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

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);
    }

BlobStorageService.cs

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);
            }
        }
    }
}

Единственное, о чем я мог подумать, это может вызвать проблему, это то, что определен тип файла, т.е. jpg в строке вместо того, чтобы быть взятым из загруженного файла. Загруженные файлы: всегда jpg и, более того, в дальнейшем изображения будут обрабатываться для изменения размера и преобразования (при необходимости) сторонней библиотекой. Однако в качестве теста наличие типа файла в строке не представлялось проблемой, но я буду руководствоваться этим вопросом.

Ответы [ 2 ]

1 голос
/ 02 апреля 2020

Если ваш car.ImageFile имеет тип IFormFile, вы можете просто использовать поток файлов для загрузки изображения, как показано ниже. Проблема в том, что вы загружаете пустой байтовый массив.

using (var fileStream = car.ImageFile.OpenReadStream())
{
    await cloudBlockBlob.UploadFromStreamAsync(fileStream);
}

Редактировать: (в вашем коде) (Примечание: это просто идея, не проверено)

Контроллер:

[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"));
            using (var fileStream = car.ImageFile.OpenReadStream())
            {
                car.ImagePath = objBlobService.UploadFileToBlob(
                    category, 
                    id, 
                    fileName, 
                    fileStream, 
                    mimeType);
            }
            }                
            return RedirectToAction(nameof(Index));
        }
        return View(car);
    }

BlobStorageService.cs

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

    private async Task<string> UploadFileToBlobAsync(string category, int id, string strFileName, Stream fileStream, 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 && fileStream != null)
            {
                CloudBlockBlob cloudBlockBlob = cloudBlobContainer.GetBlockBlobReference(fileName);
                cloudBlockBlob.Properties.ContentType = fileMimeType;
                await cloudBlockBlob.UploadFromStreamAsync(fileStream).ConfigureAwait(false);
                return cloudBlockBlob.Uri.AbsoluteUri;
            }
            return "";
        }
        catch (Exception ex)
        {
            throw (ex);
        }
    }
1 голос
/ 02 апреля 2020

Одна проблема, которую я вижу в вашем коде, заключается в том, что вы просто инициализируете массив fileData, но не заполняете его фактическими байтами файла.

byte[] fileData = new byte[car.ImageFile.Length];

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

Каким-то образом вам нужно будет заполнить этот массив данными (изображения), загруженными пользователем.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...