【问题标题】:upload large files (> 1 GB) to azure blob storage through web api通过 web api 将大文件 (> 1 GB) 上传到 azure blob 存储
【发布时间】:2020-03-02 15:01:26
【问题描述】:

我们有一个托管在 azure app 服务中的应用程序(.Net 核心),我们正在尝试使用 UI 中的表单数据通过 Web API 将大文件上传到 Azure blob。我们更改了请求长度和 API 请求超时,即使上传 200MB 文件,我们仍然面临连接超时错误

下面是我正在使用的示例代码

[HttpPost]
[Route("upload")]
[Consumes("multipart/form-data")]
[RequestFormLimits(MultipartBodyLengthLimit = 2147483648)]
public async Task<IHttpActionResult> Upload([FromForm] FileRequestObject fileRequestObject)
{
    var url = "upload_url_to_blob_storage";
    var file = fileRequestObject.Files[0];

    var blob = new CloudBlockBlob(new Uri(url));
    blob.Properties.ContentType = file.ContentType;

    await blob.UploadFromStreamAsync(file.InputStream);

    //some other operations based on file upload
    return Ok();
}


public class FileRequestObject
{
    public List<IFormFile> Files { get; set; }
    public string JSON { get; set; }
    public string BlobUrls { get; set; }

}

【问题讨论】:

  • 是否可以选择使用 API 生成 SAS 令牌,然后将文件直接上传到 blob 存储区?
  • 您确定没有达到 PUT 操作的块 Blob 大小限制吗?``` 对于版本 2016-05-31 和更高版本,旧版本为 64 MB。如果您的 blob 对于 2016-05-31 及更高版本大于 256 MB,或者对于旧版本大于 64 MB,则必须将其作为一组块上传。``` 更多详细信息,请参阅docs.microsoft.com/en-us/rest/api/storageservices/put-blob跨度>
  • @kgalic 不,我们在 API 中完成了上传操作,我们正在将流数据传递到 API 端点,然后从那里上传到 blob
  • 如果块 Blob 大小限制超出,我们是否会收到超时错误
  • @RamakrishnaReddy,请与我们分享您使用的代码,并删除个人数据/秘密。

标签: c# azure asp.net-core azure-blob-storage asp.net-core-webapi


【解决方案1】:

根据您的代码,您希望将一个大文件作为 blockblob 上传到 Azure blob 存储。请注意,它有一个限制。更多详情请参考document

通过 Put Blob 创建的块 Blob 的最大大小为 256 MB 2016-05-31 及更高版本,旧版本为 64 MB。如果你的 对于版本 2016-05-31 及更高版本,blob 大于 256 MB,或 64 MB 对于旧版本,您必须将其作为一组块上传

所以如果你想将大文件转成azure block blob,请使用以下步骤:

1。将整个文件读取为字节,然后在代码中将文件分成更小的部分。

  • 每件可能需要 8 MB。

2。使用Put Block API 上传每件作品。

  • 在每个请求中,它都包含一个 blockid。

3。使用 Put Block List API 组成 blob。

  • 在这个请求中,您需要将body中的所有blockid按顺序排列。

例如:

[HttpPost]
        [Consumes("multipart/form-data")]
        [RequestFormLimits(MultipartBodyLengthLimit = 2147483648)]
        public async Task<ActionResult> PostAsync([FromForm]FileRequestObject fileRequestObject)
        {
            
          

            string storageAccountConnectionString = "DefaultEndpointsProtocol=https;AccountName=blobstorage0516;AccountKey=UVOOBCxQpr5BVueU+scUeVG/61CZbZmj9ymouAR9609WbqJhhma2N+WL/hvaoNs4p4DJobmT0F0KAs0hdtPcqA==;EndpointSuffix=core.windows.net";
            CloudStorageAccount StorageAccount = CloudStorageAccount.Parse(storageAccountConnectionString);
            CloudBlobClient BlobClient = StorageAccount.CreateCloudBlobClient();
            CloudBlobContainer Container = BlobClient.GetContainerReference("test");
            await Container.CreateIfNotExistsAsync();
            CloudBlockBlob blob = Container.GetBlockBlobReference(fileRequestObject.File.FileName);
            HashSet<string> blocklist = new HashSet<string>();
            var file = fileRequestObject.File;
            const int pageSizeInBytes = 10485760;
            long prevLastByte = 0;
            long bytesRemain = file.Length;

            byte[] bytes;

            using (MemoryStream ms = new MemoryStream())
            {
                var fileStream = file.OpenReadStream();
                await fileStream.CopyToAsync(ms);
                bytes = ms.ToArray();
            }

            // Upload each piece
                do
                {
                    long bytesToCopy = Math.Min(bytesRemain, pageSizeInBytes);
                    byte[] bytesToSend = new byte[bytesToCopy];
                    
                    Array.Copy(bytes, prevLastByte, bytesToSend, 0, bytesToCopy);
                    prevLastByte += bytesToCopy;
                    bytesRemain -= bytesToCopy;

                    //create blockId
                    string blockId = Guid.NewGuid().ToString();
                    string base64BlockId = Convert.ToBase64String(Encoding.UTF8.GetBytes(blockId));

                    await blob.PutBlockAsync(
                        base64BlockId,
                        new MemoryStream(bytesToSend, true),
                        null
                        );

                    blocklist.Add(base64BlockId);

                } while (bytesRemain > 0);

            //post blocklist
            await blob.PutBlockListAsync(blocklist);



            return Ok();
            // For more information on protecting this API from Cross Site Request Forgery (CSRF) attacks, see https://go.microsoft.com/fwlink/?LinkID=717803
        }

public class FileRequestObject
    {
        public IFormFile File { get; set; }
    }

更多详情请参考https://www.red-gate.com/simple-talk/cloud/platform-as-a-service/azure-blob-storage-part-4-uploading-large-blobs/

【讨论】:

  • 它在没有“可写”的情况下对我有用,即MemoryStream(bytesToSend)
猜你喜欢
  • 2015-06-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-12
  • 2016-08-18
  • 2015-06-16
  • 2017-01-24
相关资源
最近更新 更多