Files uploaded to Azure Storage are corrupted

2019-08-24 18:25发布

问题:

I am trying to allow users to upload images to my web site via an HTML5 page and am trying to use Azure Blob storage. I have created the page and the C# code on the backend but it seems that the images are getting corrupted during the upload process. I am able to take the images and pass it to Azure and it creates the blob and fills it of the right size but when the images is downloaded and then open I just get a bunch of garbage (random letters and symbols) instead of the image. Can anyone help me figure this out, been trying to fix this for over a week now.

[HttpPost, ValidateAntiForgeryToken]
public ActionResult AddSection(AddEditSectionVM model, HttpPostedFileBase LogoFile)
{
    try
    {
        using (var db = new SectionContext())
        {
            if (db.Sections.Where(s => s.Route == model.Route).Count() > 0)
            {
                ModelState.AddModelError("Section Route Used", "A section with the same route already exists.");
            }

            if (LogoFile != null)
            {
                if (FileHelper.IsValidImage(LogoFile))
                {
                    ModelState.AddModelError("Invalid File Type.", "Images must be JPG, GIF, or PNG files.");
                }
            }

            if (ModelState.IsValid)
            {
                if (LogoFile != null)
                {
                    string FileName = "Images/" + model.Route + "/Core/Logo" + Path.GetExtension(LogoFile.FileName).ToLower();
                    model.LogoFileID = FileHelper.UploadFile(FileName, "site", LogoFile);
                }

                var NewSection = new Section()
                {
                    LogoFileID = model.LogoFileID,
                    Route = model.Route,
                    Title = model.Title,
                    Type = model.Type,
                    Synopsis = model.Synopsis
                };

                db.Sections.Add(NewSection);
                db.SaveChanges();
                ViewBag.Results = "New section added.";
            }

            return View(model);
        }
    }
    catch (Exception ex)
    {
        ErrorSignal.FromCurrentContext().Raise(ex);
        ViewBag.Results = "Error saving section, please try again later.";
        return View(model);
    }
 }

public static int UploadFile(string FileName, string Container, HttpPostedFileBase UploadedFile, int ExistingFileID = 0)
{
    var StorageAccount = CloudStorageAccount.Parse(ConfigurationManager.AppSettings["StorageConnectionString"]);
    var BlobClient = StorageAccount.CreateCloudBlobClient();
    var StorageContainer = BlobClient.GetContainerReference(Container);
    var BlobBlock = StorageContainer.GetBlockBlobReference(FileName);
    BlobBlock.Properties.ContentType = UploadedFile.ContentType;

    using (UploadedFile.InputStream)
    {
        BlobBlock.UploadFromStream(UploadedFile.InputStream);
    }

    using (var db = new SectionContext())
    {
        var NewFile = new DAL.File();

        if (ExistingFileID > 0)
        {
            NewFile = db.Files.Find(ExistingFileID);
            NewFile.Name = FileName;
            NewFile.ContentType = UploadedFile.ContentType;
            db.Entry(NewFile).State = EntityState.Modified;
            db.SaveChanges();
            return ExistingFileID;
        }
        else
        {
            NewFile.Name = FileName;
            NewFile.ContentType = UploadedFile.ContentType;
            db.Files.Add(NewFile);
            db.SaveChanges();
            return NewFile.ID;
        }

    }
}

Link to broken image uploaded from this code: https://gisstore01.blob.core.windows.net/ffinfofiles/ChocoboontheJob/Core/Logo.jpg

回答1:

This is what I'm using to accept logo images...

var memoryStream = new MemoryStream();

logoFile.InputStream.CopyTo(memoryStream); //logoFile is HttpPostedFileBase
memoryStream.Position = 0;
await transferService.Upload(memoryStream, fileName, "merchant-app-data", true);

memoryStream.Close();
memoryStream.Dispose();

Here is the actual upload method

public async Task<string> Upload(MemoryStream stream, string fileName, string folder, bool overwrite = false)
{
    var blobClient = _storageAccount.CreateCloudBlobClient();
    var container = blobClient.GetContainerReference(folder);
    await container.CreateIfNotExistsAsync();

    var blockBlob = container.GetBlockBlobReference(fileName);

    blockBlob.UploadFromStream(stream);

    return blockBlob.StorageUri.PrimaryUri.AbsolutePath;
}


回答2:

Your code looks fine. I did a quick prototype using as much of your code as possible to see if there was anything to watch out for, but everything seems to work fine.

My guess is the problem is not on the upload itself but on the access to the container. By default Blob containers will not allow public anonymous access.

In order to change that, the easier way is to go on Visual Studio, connect to your Azure instance via Server Explorer then find your Blob container and click on it. On the properties window you should see an entry for Public Read Access and three options: Off, Container or Blob.

If it's Off, then that's your problem! Choose either Container or Blob depending on your needs though it's safer to choose Blob. The difference being that with Blob anonymous users only have access to the data in your blobs but cannot access anything on the Blob level, so for instance, they can't enumerate all blobs in the container, but they can download an image via the blob link.

If you want to read more about container permissions here's the MSDN link for it : https://azure.microsoft.com/en-us/documentation/articles/storage-manage-access-to-resources/

Hope this helps. If not, let us know and we'll keep trying.