You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#中使用CopyTo()后原始流丢失,Azure Blob文件损坏求助

问题分析与解决方案

核心问题

你遇到的文件损坏问题,根源在于用字符串中转二进制流的处理方式:

  1. StreamReader是为纯文本设计的,读取二进制文件(如图片、PDF、Office文档)时,会因编码转换丢失原始字节数据。
  2. writer.WriteLine(fileContent)会在内容末尾额外添加换行符,篡改了原始文件的内容结构。
  3. 原代码中FileStream未用using包裹,可能导致文件写入不完整或资源泄漏。

推荐解决方案(兼容所有文件类型)

直接操作流的字节数据,避免字符串中转,通过MemoryStream备份源流,分别完成本地写入和Blob上传:

var stream = await this.DownloadFromSPO(pipeline).ConfigureAwait(false);
if (stream == null)
{                
    return false;
}

// 备份源流到MemoryStream,避免操作后位置偏移
using var backupStream = new MemoryStream();
await stream.CopyToAsync(backupStream).ConfigureAwait(false);
// 重置两个流的读取位置到起始点
stream.Position = 0;
backupStream.Position = 0;

// 保存到本地文件夹(使用using确保流正确释放)
string filePath2 = Path.Combine("C:\\localLocation", pipeline.Name);
using var outputFileStream = new FileStream(filePath2, FileMode.Create);
await backupStream.CopyToAsync(outputFileStream).ConfigureAwait(false);

// 上传到Azure Blob(重置源流位置后直接使用)
CloudBlob blob = null;
await AzureRetryHelper.OperationWithBasicRetryAsync(async () =>
{
    stream.Position = 0;
    blob = await this.blobHelper.UploadFileToBlob(
        stream,
        this.config.GetConfigValue(Constants.DataContainerName),
        pipeline.BlobNativeFilePath,
        true,
        pipeline.MimeType).ConfigureAwait(false);
}).ConfigureAwait(false);

仅适用于纯文本文件的备选方案

如果你确认所有处理的都是纯文本文件,可以调整字符串中转逻辑,避免篡改内容:

1. 修改GetStream方法

public static Stream GetStream(string fileContent, Encoding encoding)
{
    MemoryStream ms = new MemoryStream();
    // 保持编码一致,且leaveOpen设为true避免提前关闭MemoryStream
    using StreamWriter writer = new StreamWriter(ms, encoding, leaveOpen: true);
    writer.Write(fileContent); // 用Write替代WriteLine,避免添加额外换行
    writer.Flush();
    ms.Seek(0, SeekOrigin.Begin);
    return ms;
}

2. 调整主逻辑代码

var stream = await this.DownloadFromSPO(pipeline).ConfigureAwait(false);
if (stream == null)
{                
    return false;
}

string filePath2 = Path.Combine("C:\\localLocation", pipeline.Name);
string content = string.Empty;
// 指定与原始文件一致的编码(如UTF8、GB2312等)
using (StreamReader reader = new StreamReader(stream, Encoding.UTF8))
{      
    content = reader.ReadToEnd();         
    // 直接写入文本内容,避免编码错误
    using var outputFileStream = new FileStream(filePath2, FileMode.Create);
    using var fileWriter = new StreamWriter(outputFileStream, Encoding.UTF8);
    fileWriter.Write(content);
}          

// 用一致的编码重建流
stream = helper.GetStream(content, Encoding.UTF8);

// 上传到Azure Blob
CloudBlob blob = null;
await AzureRetryHelper.OperationWithBasicRetryAsync(async () =>
{
    blob = await this.blobHelper.UploadFileToBlob(
        stream,
        this.config.GetConfigValue(Constants.DataContainerName),
        pipeline.BlobNativeFilePath,
        true,
        pipeline.MimeType).ConfigureAwait(false);
}).ConfigureAwait(false);

关键注意事项

  • 处理非文本文件时,禁止用字符串中转流,必须直接操作字节数据。
  • 所有流对象务必用using包裹,确保资源正确释放。
  • 每次读取流前,必须重置Position = 0,否则会从流的末尾开始读取,导致空数据。

内容的提问来源于stack exchange,提问作者Neelam

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 18:15:13