为啥通过内存流上传 JSON 时 BlobClient.UploadAsync 会挂起?

Posted

技术标签:

【中文标题】为啥通过内存流上传 JSON 时 BlobClient.UploadAsync 会挂起?【英文标题】:Why does BlobClient.UploadAsync hang when uploading JSON via a memory stream?为什么通过内存流上传 JSON 时 BlobClient.UploadAsync 会挂起? 【发布时间】:2020-10-09 17:53:13 【问题描述】:

我正在尝试通过内存流将 JSON 上传到 Azure blob。当我调用 UploadAsync 我的应用程序挂起。如果我将 UploadAsync 调用移到 StreamWriter 大括号之外,我会得到一个 System.ObjectDisposedException: 'Cannot access a closed Stream。'例外。如何将 JSON 流式传输到 blob?

            var blobClient = new BlobClient(new Uri(storageUri), options);

            var serializer = JsonSerializer.Create(this.serializerSettings);

            using (var stream = new MemoryStream())
            
                using (var writer = new StreamWriter(stream))
                
                    serializer.Serialize(writer, job);

                    await blobClient.UploadAsync(stream, overwrite: true, cancellationToken: cancellationToken);
                
            

【问题讨论】:

1) 您需要在序列化后刷新StreamWriter,最好将其放在using 语句中并且不关闭底层流(参见here)。 2)您需要在上传之前通过设置stream.Position = 0来倒带MemoryStream。不知道这些是否导致挂起。 似乎这是 Is there any way to close a StreamWriter without closing its BaseStream? 和 Stream.Seek(0, SeekOrigin.Begin) or Position = 0 的副本。 This answer 到 MemoryStream - Cannot access a closed Stream 准确显示了要做什么。同意吗? 感谢您的回复。我查看了那个帖子,但它没有显示正在刷新的流。 通过using 语句处理StreamWriter 会刷新它。链接的答案显示了如何在不关闭基础流的情况下做到这一点。 谢谢,我已经使用链接的答案更新了我的答案。 【参考方案1】:

我使用 leaveOpen 选项来保持内存流打开。在上传到 blob 之前,我还重绕了内存流。

            var blobClient = new BlobClient(new Uri(storageUri), options);

            var serializer = JsonSerializer.Create(this.serializerSettings);

            using (var stream = new MemoryStream())
            
                // Use the 'leave open' option to keep the memory stream open after the stream writer is disposed
                using (var writer = new StreamWriter(stream, Encoding.UTF8, 1024, true))
                
                    // Serialize the job to the StreamWriter
                    serializer.Serialize(writer, job);
                

                // Rewind the stream to the beginning
                stream.Position = 0;

                // Upload the job via the stream
                await blobClient.UploadAsync(stream, overwrite: true, cancellationToken: cancellationToken);
            

【讨论】:

以上是关于为啥通过内存流上传 JSON 时 BlobClient.UploadAsync 会挂起?的主要内容,如果未能解决你的问题,请参考以下文章

intent传对象为啥要序列化

FAST DFS 流上传

FAST DFS 流上传

在播放框架 2.0 中将文件作为流上传

html 读取本地文件后使用文件二进制流上传文件

小程序base64图片解析成流上传服务器