使用.NET 8上传Gzip压缩CSV至Azure Blob后的文件异常问题
问题分析与解决方案
问题根源
- GZip压缩流未完成完整压缩流程:当前代码中,
GZipStream、StreamWriter的释放时机在Blob上传之后,导致写入MemoryStream的是不完整的压缩数据(缺少gzip归档必需的尾部校验信息)。这直接导致下载后的文件无法被Windows、Databricks识别,同时大小计算出现异常。 - Content-Type设置不符合标准:压缩后的文件本质是gzip归档,原代码设置的
application/csv无法让工具正确识别文件类型,仅Blob Explorer通过ContentEncoding字段兼容识别。
修正后的代码
public async Task SaveAsync ( IEnumerable<MyData> data, string containerName, string blobName, CancellationToken cancellationToken ) { using var ms = new MemoryStream(); var containerClient = _blobServiceClient.GetBlobContainerClient(containerName); await containerClient.CreateIfNotExistsAsync(); var blobClient = containerClient.GetBlobClient(blobName); // 限制流作用域,确保数据写入后立即完成压缩 await using (var compress = new GZipStream(ms, CompressionMode.Compress, true)) await using (var writer = new StreamWriter(compress)) await using (var csv = new CsvWriter(writer, CultureInfo.InvariantCulture, true)) { csv.Context.RegisterClassMap<MyData>(); await csv.WriteRecordsAsync(data.OrderBy(x => x.Date), cancellationToken); await writer.FlushAsync(cancellationToken); await compress.FlushAsync(cancellationToken); } // 此处自动释放流,GZipStream写入完整的压缩尾部信息 ms.Position = 0; var blobHttpHeader = new BlobHttpHeaders { ContentType = "application/gzip", // 修正为gzip归档类型 ContentEncoding = "gzip", }; IDictionary<string, string> metaData = new Dictionary<string, string>(); metaData.Add("date", DateTime.UtcNow.ToString(CultureInfo.InvariantCulture)); await blobClient.UploadAsync ( ms, blobHttpHeader, metaData, null, null, null, default, cancellationToken ); }
关键修正点
- 压缩流作用域控制:用大括号将
GZipStream、StreamWriter、CsvWriter包裹,确保数据写入完成后立即释放流,触发GZipStream完成完整压缩流程,生成合法的gzip归档文件。 - Content-Type修正:将
ContentType设为application/gzip,让Windows、Databricks等工具能直接识别文件为gzip压缩格式。 - 强制刷新流:增加对
GZipStream的FlushAsync调用,确保所有压缩数据写入MemoryStream。
内容的提问来源于stack exchange,提问作者ARV
相关产品推荐
相关产品推荐

