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

上传至Azure Blob容器的文件大小与原始文件不符问题求助

问题根因

你的代码存在几个核心逻辑错误,直接导致大文件仅上传了部分数据:

  • 未校验文件流读取的实际字节数
    FileStream.Read() 方法不保证每次都返回你请求的bytesToRead长度的数据,实际返回值才是本次读取到的有效字节数,你直接忽略该返回值,默认读取到了完整的块长度。一旦某次读取返回的字节数小于请求值,你后续仍按完整块大小更新bytesToUpload等计数变量,会导致计数提前归零,循环提前终止,仅上传了部分数据。你最终得到的3.12GB文件刚好是100个32MB块的总大小,说明循环仅执行了100次就提前退出。
  • 异步操作无异常校验和重试机制
    你调用的PutBlockAsync是异步方法,仅通过ContinueWith执行后续逻辑,但完全没有判断异步任务的执行状态,一旦某个块因为网络波动、存储配额不足、权限不足等原因上传失败,你没有任何感知,仍继续执行后续流程,最终提交的块列表中会缺失对应块,或存在无效块。
  • 异步方法未做等待逻辑
    你的方法名义上是异步方法,但返回值为void,所有异步操作都没有暴露等待入口,外部调用该方法时很容易在所有块上传、块列表提交操作完成前就结束进程,导致上传流程中途中断。
  • 不必要的文件流重复打开
    你每次循环都重新打开一次本地文件,频繁打开100GB级别的大文件会大幅提升IO异常概率,也会严重拖累上传性能,全程复用一个文件流即可。

修复后的核心逻辑参考

// 建议改成异步方法返回Task
public async Task UploadStreamAsync(string file)
{
    var fileInfo = new FileInfo(file);
    CloudBlockBlob myBlob = _container.GetBlockBlobReference(fileInfo.Name);
    var blockSize = 32 * 1024 * 1024;
    myBlob.StreamWriteSizeInBytes = blockSize;
    long bytesToUpload = fileInfo.Length;
    List<string> blockIds = new List<string>();
    int index = 1;

    // 复用同一个文件流
    using (FileStream fs = new FileStream(fileInfo.FullName, FileMode.Open, FileAccess.Read))
    {
        while (bytesToUpload > 0)
        {
            var bytesToRead = (int)Math.Min(blockSize, bytesToUpload);
            var blobContents = new byte[bytesToRead];
            // 校验实际读取的字节数
            int bytesRead = await fs.ReadAsync(blobContents, 0, bytesToRead);
            if (bytesRead == 0) break; // 读取到文件末尾

            var blockId = Convert.ToBase64String(Encoding.UTF8.GetBytes(index.ToString("d6")));
            blockIds.Add(blockId);
            // 等待块上传完成,可自行补充异常重试逻辑
            using (var ms = new MemoryStream(blobContents, 0, bytesRead))
            {
                await myBlob.PutBlockAsync(blockId, ms, null);
            }

            bytesToUpload -= bytesRead;
            double percentComplete = (double)(fileInfo.Length - bytesToUpload) / (double)fileInfo.Length;
            _logger.LogInformation("Percent complete = {Percent}", percentComplete.ToString("P"));
            index++;
        }
    }

    // 等待块列表提交完成
    await myBlob.PutBlockListAsync(blockIds);
    _logger.LogInformation("Blob uploaded completely.");
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 14:00:04