如何使用.NET将大文件上传到Azure容器?

时间:2019-03-01 10:43:47

标签: c# .net azure file-upload azure-storage-blobs

我试图使用Windows窗体应用程序将大文件上传到azure容器。

由于文件很大,因此我无法将其作为单个块上传。

找到了一种以块为单位上传大文件的方法。 我将代码发布在这里,希望可以帮助有类似要求的人。

1 个答案:

答案 0 :(得分:2)

我们可以使用Block blobs将大文件上传到Azure容器。

Block blobs由多个块组成,每个块均由一个块ID标识。

当我们将一个块上传到Blob时,它与指定的块Blob相关联,但是在您提交包含新块ID的块列表之前,它不会成为Blob的一部分。

块ID是blob中长度相等的字符串。

块客户端代码通常使用base-64编码将字符串标准化为相等的长度。 使用base-64编码时,预编码的字符串必须小于等于64个字节。

有关更多信息,请阅读文档here

以下代码将源文件拆分为每个大小为10MB的多个字节数组。 使用 Put Block 操作将每个字节数组上传为块。 这些块将与指定的Block blob关联。

稍后使用 Put Block List 操作提交blockID,这将使用blockID从上传的块中创建blob。

public string UploadFile(string sourceFilePath)
{
    try
    {
        string storageAccountConnectionString = "AZURE_CONNECTION_STRING";
        CloudStorageAccount StorageAccount = CloudStorageAccount.Parse(storageAccountConnectionString);
        CloudBlobClient BlobClient = StorageAccount.CreateCloudBlobClient();
        CloudBlobContainer Container = BlobClient.GetContainerReference("container-name");
        Container.CreateIfNotExists();
        CloudBlockBlob blob = Container.GetBlockBlobReference( Path.GetFileName(sourceFilePath) );
        HashSet<string> blocklist = new HashSet<string>();

        byte[] fileContent = File.ReadAllBytes(sourceFilePath);
        const int pageSizeInBytes = 10485760;
        long prevLastByte = 0;
        long bytesRemain = fileContent.Length;

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

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

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

            blocklist.Add(base64BlockId);

        } while (bytesRemain > 0);

        //post blocklist
        blob.PutBlockList(blocklist);

        return "Success";
    }
    catch (Exception ex)
    {
        return ex.Message;
    }
}