【问题标题】:Overwrite contents of existing content in Azure Blob Storage覆盖 Azure Blob 存储中现有内容的内容
【发布时间】:2018-06-27 06:59:51
【问题描述】:

我正在使用块 blob 通过 Azure 存储客户端在 Azure blob 存储中附加时间序列数据。我现在想更新现有 blob 的内容。文件大小可高达 800MB。

有没有办法根据blockId分块下载blob,更改内容并上传该blockId的内容?

【问题讨论】:

    标签: azure azure-blob-storage


    【解决方案1】:

    有没有办法根据blockId分块下载blob,改 内容并上传那个blockId的内容?

    AFAIK,我认为目前无法使用现有的 API。当前的 API 只为您提供块 ID 和块的大小。为此,您需要在某个位置存储块的元数据(如块 ID、开始/结束字节范围)。

    一种可能的解决方案(只是大声思考)是利用 blob 的元数据来存储该块的元数据。您可以读取元数据,获取要下载的字节范围,下载该数据,对其进行修改,然后将其上传回来。再次上传时,您需要调整有关块的元数据。但是元数据大小(8K 字节)也有限制。

    【讨论】:

      【解决方案2】:

      您可以使用 .NET 库 Microsoft.WindowsAzure.StorageMicrosoft.WindowsAzure.Storage.Blob 来做到这一点

      假设您想从一个非常大的 csv 文件中删除标题行,但只下载并上传第一个块:

      using Microsoft.WindowsAzure.Storage;
      using Microsoft.WindowsAzure.Storage.Blob;
      using System;
      using System.IO;
      using System.Linq;
      using System.Threading.Tasks;
      
      namespace RemoveHeaderRow
      {
          class Program
          {
              static async Task Main(string[] args)
              {
                  var storageAccount = CloudStorageAccount.Parse("DefaultEndpointsProtocol=https;AccountName=...;AccountKey=...;EndpointSuffix=core.windows.net");
                  var client = storageAccount.CreateCloudBlobClient();
                  var container = client.GetContainerReference("containerName");
                  var blockBlob = container.GetBlockBlobReference("blobName.csv");
      
                  var blockList = await blockBlob.DownloadBlockListAsync();
                  if (blockList.Count() == 0)
                  {
                      // not all blocks have a blocklist, here's why: https://stackoverflow.com/questions/14652172/azure-blobs-block-list-is-empty-but-blob-is-not-empty-how-can-this-be
                      return; // cannot proceed
                  }
                  var firstBlock = blockList.First();
      
                  //  download block
                  var contents = await GetBlockBlobContents(blockBlob, firstBlock);
      
                  //  remove first line
                  var noHeaderContents = string.Join("\n", contents.Split("\n").Skip(1));
      
                  //  upload block back to azure
                  await UpdateBlockBlobContent(blockBlob, firstBlock, noHeaderContents);
      
                  //  commit the blocks, all blocks need to be committed, not just the updated one
                  await blockBlob.PutBlockListAsync(blockList.Select(b => b.Name));
              }
      
              public static async Task<string> GetBlockBlobContents(CloudBlockBlob blockBlob, ListBlockItem blockItem)
              {
                  using (var memStream = new MemoryStream())
                  using (var streamReader = new StreamReader(memStream))
                  {
                      await blockBlob.DownloadRangeToStreamAsync(memStream, 0, blockItem.Length);
                      memStream.Position = 0;
                      return await streamReader.ReadToEndAsync();
                  }
              }
      
              public static async Task UpdateBlockBlobContent(CloudBlockBlob blockBlob, ListBlockItem blockItem, string contents)
              {
                  using (var stream = new MemoryStream())
                  using (var writer = new StreamWriter(stream))
                  {
                      writer.Write(contents);
                      writer.Flush();
                      stream.Position = 0;
                      await blockBlob.PutBlockAsync(blockItem.Name, stream, null);
                  }
              }
          }
      }
      

      【讨论】:

        猜你喜欢
        • 2016-12-07
        • 2016-08-30
        • 2014-09-09
        • 1970-01-01
        • 2021-10-05
        • 2021-09-17
        • 1970-01-01
        • 2012-07-15
        • 1970-01-01
        相关资源
        最近更新 更多