简体   繁体   English

为什么我上传到 Azure 的图像包含阻止它们显示的错误?

[英]Why do my uploaded images to Azure contain errors preventing them being displayed?

I have uploaded images to my blob storage account in Azure, whenever I try to access those images either via a web browser or via the azure container explorer I get an error of我已将图像上传到 Azure 中的 blob 存储帐户,每当我尝试通过 Web 浏览器或通过 azure 容器资源管理器访问这些图像时,我都会收到错误消息

The image "whatever.jpg" cannot be displayed because it contains errors.图像“whatever.jpg”无法显示,因为它包含错误。

It doesn't give me any more information than that, looking at the file in Azure explorer I can see that it's been named correctly, has the correct image type, has data as in I can see the bytes.它没有给我更多的信息,查看 Azure 资源管理器中的文件,我可以看到它被正确命名,具有正确的图像类型,具有数据,因为我可以看到字节。

I've looked at the access rights and I've set the container folder to be public read access as to not require a key.我查看了访问权限,并将容器文件夹设置为公共read access ,因此不需要密钥。 To further test for errors, I uploaded the same images via the azure dashboard directly to the storage account and they work, therefore the problem must be in the way I'm uploaded them.为了进一步测试错误,我通过 azure 仪表板将相同的图像直接上传到存储帐户并且它们可以工作,因此问题一定出在我上传它们的方式上。

For the sake of context, I am using a blob storage service in my application with dependency injection for use in my controller.考虑到上下文,我在我的应用程序中使用 blob 存储服务,并在我的控制器中使用依赖注入。

Create创建

@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汽车控制器.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 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);
            }
        }
    }
}

The only thing I could think of that might cause a problem is that the file type ie jpg is defined in the string instead of being taken from the uploaded file.我能想到的唯一可能会导致问题的是文件类型,即 jpg 是在字符串中定义的,而不是从上传的文件中获取的。 The files that are uploaded are always jpg and furthermore, down the line, the images will be processed for resizing and converting (if needed) by a third party library.上传的文件始终为 jpg ,此外,在此之后,第三方库将处理图像以调整大小和转换(如果需要)。 As a test, however, having the filetype in the string didn't seem to be an issue but I'll take guidance on that.然而,作为测试,在字符串中包含文件类型似乎不是问题,但我会就此提供指导。

One issue I see in your code is that you're simply initializing the fileData array but not populating it with actual file bytes.我在您的代码中看到的一个问题是,您只是在初始化fileData数组,而不是用实际的文件字节填充它。

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

So actually you're uploading a file with all bytes as zero.所以实际上你正在上传一个所有字节为零的文件。

Somehow you will need to fill this array with the data (image) uploaded by the user.不知何故,你需要用用户上传的数据(图像)填充这个数组。

If your car.ImageFile is type IFormFile you can simply use the file stream to upload the image like below.如果您的 car.ImageFile 是 IFormFile 类型,您可以简单地使用文件流上传图像,如下所示。 The problem is that you are uploading an empty byte array.问题是您正在上传一个空字节数组。

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

Edit: (In Your Code) (Note: this is just an idea, untested)编辑:(在您的代码中)(注意:这只是一个想法,未经测试)

Controller:控制器:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM