【问题标题】:Files uploaded to Azure Storage are corrupted上传到 Azure 存储的文件已损坏
【发布时间】:2015-08-02 22:14:18
【问题描述】:

我正在尝试允许用户通过 HTML5 页面将图像上传到我的网站,并尝试使用 Azure Blob 存储。我已经在后端创建了页面和 C# 代码,但似乎图像在上传过程中被损坏了。我能够获取图像并将其传递给 Azure,它会创建 blob 并将其填充为正确的大小,但是当图像被下载然后打开时,我只会得到一堆垃圾(随机字母和符号)而不是图像.谁能帮我解决这个问题,已经尝试解决这个问题一个多星期了。

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

    }
}

从此代码上传的损坏图片的链接:https://gisstore01.blob.core.windows.net/ffinfofiles/ChocoboontheJob/Core/Logo.jpg

【问题讨论】:

  • 你是如何下载文件的?
  • @JacobRoberts 通过 Azure 门户,我只需浏览并使用“下载”按钮,然后保存到桌面。如果我转到完整的 URL,它是一个损坏的图像。我可以通过 Azure SDK 上传相同的图像,它可以正常工作吗?所以它必须是代码中的东西
  • 您可以尝试将流位置设置为 0,而不是 CloudBlockBlob,而是使用 CloudBlob,这对于您的图像大小来说应该足够了,直到一些 MB。
  • @MaheshJasti 我不确定如何设置流位置,因为我没有先读入内存,而且我不确定您使用 CloudBlob 而不是 BloudBlockBlob 作为唯一位置是什么意思我创建的 blob 是 CreateCloudBlobClient。你能给我一些你想让我修改的代码示例吗?
  • 在您的代码中,而不是 GetBlockBlobReference(FileName);,尝试使用 GetBlobReference("") 并继续使用 Blob 而不是 BlockBlob。

标签: c# azure azure-blob-storage


【解决方案1】:

这是我用来接受徽标图像的...

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

这里是实际的上传方法

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】:

您的代码看起来不错。我使用尽可能多的代码做了一个快速原型,看看是否有什么需要注意的地方,但一切似乎都很好。

我的猜测是问题不在于上传本身,而在于对容器的访问。默认情况下,Blob 容器不允许公共匿名访问。

为了改变这一点,更简单的方法是继续使用 Visual Studio,通过服务器资源管理器连接到您的 Azure 实例,然后找到您的 Blob 容器并单击它。在属性窗口中,您应该会看到 Public Read Access 条目和三个选项:Off、Container 或 Blob。

如果它关闭,那就是你的问题!根据您的需要选择 Container 或 Blob,尽管选择 Blob 更安全。不同之处在于,对于 Blob,匿名用户只能访问 Blob 中的数据,但不能访问 Blob 级别的任何内容,例如,他们无法枚举容器中的所有 Blob,但他们可以通过 Blob 下载图像链接。

如果您想了解有关容器权限的更多信息,请查看 MSDN 链接:https://azure.microsoft.com/en-us/documentation/articles/storage-manage-access-to-resources/

希望这会有所帮助。如果没有,请告诉我们,我们会继续努力。

【讨论】:

  • 权限设置正确,文件有公共读取权限。这与上传有关,因为我可以使用 Azure SDK 在容器中放置一个 blob,并且一切正常。相同的容器,相同的文件,相同的一切通过 Azure SDK 工作,但通过用户上传不能。
猜你喜欢
  • 1970-01-01
  • 2018-07-12
  • 2020-04-05
  • 2013-10-24
  • 2023-03-20
  • 2020-01-14
  • 1970-01-01
  • 2018-12-30
  • 2017-06-27
相关资源
最近更新 更多