【问题标题】:Azure Storage: BlobClient keeps resetting itself while uploading large filesAzure 存储:BlobClient 在上传大文件时不断自我重置
【发布时间】:2020-12-29 23:07:27
【问题描述】:

我正在尝试从连接到快速 Wifi 连接的手机上传 200 MB 的视频文件。我正在使用适用于 .NET 的 Azure Storage SDK v12,但以下代码在大约 30% 的上传进度后会自行重置。重置时,进度从 0 开始,不抛出异常。

await blobClient.UploadAsync(stream, progressHandler: new Progress<long>(progress =>
{
     // show progress bar
}), cancellationToken: cancellationToken);

v12 支持上传大文件吗?如果我没记错的话,旧的 API 可以上传单个块。我的印象是上面的上传方法会隐式处理分块。

如何使用最新的 sdk 上传大文件?

附:我尝试以非常高的并发性和 1 MB 的传输大小传递 StorageTransferOptions,但没有任何区别。

编辑:等待了很长时间,我能够得到一个异常抛出。我看到多个任务因为

而被取消
Cannot access a disposed object.
Object name: 'MobileAuthenticatedStream'.

  at Mono.Net.Security.MobileAuthenticatedStream.StartOperation (Mono.Net.Security.MobileAuthenticatedStream+OperationType type, Mono.Net.Security.AsyncProtocolRequest asyncRequest, System.Threading.CancellationToken cancellationToken) [0x00245] in /Users/builder/jenkins/workspace/archive-mono/2020-02/android/release/mcs/class/System/Mono.Net.Security/MobileAuthenticatedStream.cs:410 
  at System.Net.Http.HttpConnection.WriteAsync (System.ReadOnlyMemory`1[T] source) [0x00118] in /Users/builder/jenkins/workspace/archive-mono/2020-02/android/release/external/corefx/src/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpConnection.cs:1008 
  at System.IO.Stream.CopyToAsyncInternal (System.IO.Stream destination, System.Int32 bufferSize, System.Threading.CancellationToken cancellationToken) [0x000e7] in /Users/builder/jenkins/workspace/archive-mono/2020-02/android/release/external/corert/src/System.Private.CoreLib/shared/System/IO/Stream.cs:152 
  at Azure.Core.RequestContent+StreamContent.WriteToAsync (System.IO.Stream stream, System.Threading.CancellationToken cancellation) [0x00094] in <7b1dc95b0b4841539beb48023c1128d3>:0 
  at Azure.Core.Pipeline.HttpClientTransport+PipelineRequest+PipelineContentAdapter.SerializeToStreamAsync (System.IO.Stream stream, System.Net.TransportContext context) [0x0007c] in <7b1dc95b0b4841539beb48023c1128d3>:0 
  at System.Net.Http.HttpContent.CopyToAsyncCore (System.Threading.Tasks.ValueTask copyTask) [0x00022] in /Users/builder/jenkins/workspace/archive-mono/2020-02/android/release/external/corefx/src/System.Net.Http/src/System/Net/Http/HttpContent.cs:361 

所以blobClient 中似乎内置了并行化,但它仍然失败了。此外,我不能使用https://www.nuget.org/packages/Microsoft.Azure.Storage.DataMovement,因为它不适用于Xamarin Forms

【问题讨论】:

    标签: azure xamarin azure-storage azure-blob-storage


    【解决方案1】:

    如果要将文件分块上传到 Azure Blob 存储,请参考以下代码

    public async Task upload(Stream stream){
                string connectionString = "";
                string containerName = "upload";
                string blobName = "";
                BlockBlobClient blobClient = new BlockBlobClient(connectionString, containerName, blobName);
               
                List<string> blockList = new List<string>();
    
                    while (true) {
                        byte[] b = new byte[1024 * 1024];
                        var n = await stream.ReadAsync(b, 0, 1024 * 1024);
                        if (n == 0) break;
                        string blockId = Guid.NewGuid().ToString();
                        string base64BlockId = Convert.ToBase64String(Encoding.UTF8.GetBytes(blockId));
                        await blobClient.StageBlockAsync(base64BlockId, new MemoryStream(b, true));
                        blockList.Add(base64BlockId);
                    }
    
                    await blobClient.CommitBlockListAsync(blockList);
    
       
    }
    

    更新

    如果要使用sas token,请参考以下代码

    var uri = new Uri($"https://{storageAccountName}.blob.core.windows.net/{containerName}/{blobName}?{sasToken}");
    BlockBlobClient blobClient = new BlockBlobClient(uri);
    

    【讨论】:

    • 这就是我要找的。谢谢。我不向客户端发送连接字符串。相反,我使用 SAS 令牌。您能否更新您的代码以反映这一点,以便我可以接受它作为答案?另外,如何并行化?看来这段代码正在序列化块上传。
    • @user246392 你能告诉我你的意思how can this be parallelized吗?
    • 是否可以创建多个Task 对象并并行暂存块以加快上传过程?
    • @user246392 是的,您可以这样做。但是commit block list的时候,需要把所有blockid都排好序
    【解决方案2】:

    v12 同时具有 BlobClient 和 BlockBlobClient。就是BlockBlobClient,它具有分块并上传每个块的功能。

    你可以试试 Microsoft.Azure.Storage.DataMovement https://www.nuget.org/packages/Microsoft.Azure.Storage.DataMovement

    “Microsoft Azure Storage DataMovement Library 提供了一组 API 扩展现有的 Azure Storage .Net 客户端库以提供帮助 客户传输高性能 Azure Blob 和文件存储, 可扩展性和可靠性。”

    【讨论】:

    • 谢谢。我不知道这个包存在。我正在使用 Xamarin Forms 并且无法使用此包,因为我不断收到“Mono.Posix.NETStandard”参考问题。我安装了 Posix Nuget,但我仍然在 Android 项目中遇到问题。
    猜你喜欢
    • 2022-01-06
    • 2015-06-16
    • 1970-01-01
    • 2021-01-09
    • 2020-02-13
    • 2017-05-04
    • 2016-08-18
    • 2018-02-16
    • 2013-02-22
    相关资源
    最近更新 更多