BlobClient.UploadAsync上传JSON内存流时挂起及流已释放异常求助
解决JSON流式上传至Azure Blob的问题
看来你碰到了流操作里常见的两个坑:要么上传时挂起,要么流被提前关闭抛异常。我来给你拆解原因,再给几个靠谱的解决方案~
问题根源分析
在StreamWriter块内调用UploadAsync导致挂起:
当你用serializer.Serialize(writer, job)写完JSON后,MemoryStream的当前位置会停在内容末尾,而UploadAsync是从当前位置开始读取流的,自然读不到任何数据,就会一直等待,导致程序挂起。另外,StreamWriter默认会缓冲内容,可能还有部分数据没刷到MemoryStream里。移到StreamWriter块外抛出ObjectDisposedException:
默认情况下,StreamWriter的Dispose方法会关闭它所包装的底层流(也就是你的MemoryStream)。当你把UploadAsync移到using块外时,MemoryStream已经被关闭,自然无法访问。
解决方案
方案一:修复流位置与StreamWriter的Dispose行为(适配你的原有代码)
调整代码,确保流的位置正确,并且StreamWriter不会提前关闭MemoryStream:
var blobClient = new BlobClient(new Uri(storageUri), options); var serializer = JsonSerializer.Create(this.serializerSettings); using (var stream = new MemoryStream()) { // 关键:设置leaveOpen: true,让StreamWriter dispose时不关闭底层流 using (var writer = new StreamWriter(stream, leaveOpen: true)) { serializer.Serialize(writer, job); // 强制把StreamWriter缓冲区的内容刷入MemoryStream writer.Flush(); // 把流的位置重置到开头,让UploadAsync能读到完整的JSON stream.Position = 0; await blobClient.UploadAsync(stream, overwrite: true, cancellationToken: cancellationToken); } }
方案二:用SDK自带的序列化上传(最简洁)
Azure.Storage.Blobs库已经封装了直接序列化对象到Blob的方法,完全不用手动处理流:
var blobClient = new BlobClient(new Uri(storageUri), options); await blobClient.UploadAsync( BinaryData.FromObjectAsJson(job, this.serializerSettings), overwrite: true, cancellationToken: cancellationToken);
这种方式由SDK帮你处理所有流的细节,代码更简洁,也不容易出错。
方案三:直接写入Blob的上传流(适合大对象)
如果你的JSON对象很大,不想占用内存中转,可以直接打开Blob的写入流,把序列化内容直接写进去:
var blobClient = new BlobClient(new Uri(storageUri), options); var serializer = JsonSerializer.Create(this.serializerSettings); // 直接打开Blob的写入流 using (var uploadStream = await blobClient.OpenWriteAsync(overwrite: true, cancellationToken: cancellationToken)) using (var writer = new StreamWriter(uploadStream)) { serializer.Serialize(writer, job); // StreamWriter的Dispose会自动Flush缓冲区,无需手动操作 }
这种方式节省内存,适合处理大文件或大对象。
内容的提问来源于stack exchange,提问作者Dave Moran
相关产品推荐
相关产品推荐

