通过 web api 将大文件 (> 1 GB) 上传到 azure blob 存储

Ram*_*ddy 2 c# azure azure-storage-blobs asp.net-core asp.net-core-webapi

我们有一个托管在 azure 应用服务中的应用程序(.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; }

}
Run Code Online (Sandbox Code Playgroud)

Jim*_* Xu 8

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

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

因此,如果您想将大文件转为 azure 块 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; }
    }

Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明 在此处输入图片说明 更多详情请参考https://www.red-gate.com/simple-talk/cloud/platform-as-a-service/azure-blob-storage-part-4-uploading-large-blobs/