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

通过代码下载含文件夹的Azure API ZIP文件失败,浏览器下载正常

问题分析与修复方案

你的代码下载ZIP文件后损坏,主要有以下几个问题:

  1. 多余的Content-Type修改
    手动设置response.Content.Headers.ContentType.MediaType = "application/zip";完全没必要,甚至可能干扰HttpClient对响应内容的正确解析。Azure API返回的响应头已包含正确的Content-Type,无需手动修改。

  2. 流资源未正确管理
    content和file流未使用using语句,导致流无法被正确关闭、刷新,部分数据可能留在缓冲区未写入磁盘,造成文件不完整。

  3. 文件存在时未覆盖
    File.OpenWrite会在目标文件已存在时追加内容,而非覆盖,新旧内容混合直接破坏ZIP文件结构。

  4. 自动解压响应的潜在问题
    默认情况下,HttpClient会自动处理带有Content-Encoding: gzip/deflate的响应。如果Azure API返回的ZIP文件本身被gzip压缩,HttpClient会自动解压,导致写入磁盘的是解压后的内容而非原始ZIP文件,最终损坏。


修复后的代码

public async Task GetArtifact(string url)
{
    var client = CreateClient();
    // 禁用自动解压,确保拿到原始ZIP字节流
    client.DefaultRequestHeaders.AcceptEncoding.Clear();
    
    var uri = new Uri(url);
    var percentage = 0.0;

    using HttpResponseMessage response = await client.GetAsync(uri, HttpCompletionOption.ResponseHeadersRead);
    response.EnsureSuccessStatusCode(); // 直接抛出非成功状态码异常,简化逻辑
    
    var fileSize = response.Content.Headers.ContentLength;
    var fileName = response.Content.Headers.ContentDisposition.FileName;

    // 用File.Create覆盖现有文件,保证文件是全新的
    using Stream fileStream = File.Create(fileName);
    using Stream contentStream = await response.Content.ReadAsStreamAsync();
    
    var buffer = new byte[32768];
    var readByte = 0L;
    int bytesRead;
    
    while ((bytesRead = await contentStream.ReadAsync(buffer, 0, buffer.Length)) > 0)
    {
        await fileStream.WriteAsync(buffer, 0, bytesRead);
        readByte += bytesRead;
        
        if (fileSize.HasValue)
        {
            percentage = Math.Round((double)readByte / fileSize.Value * 100, 2);
            Console.WriteLine($"{percentage}%");
        }
    }
}

关键修复点说明

  • 禁用自动解压:通过client.DefaultRequestHeaders.AcceptEncoding.Clear();避免HttpClient错误解压ZIP文件,确保获取原始字节流。
  • using语句管理资源:所有流和HttpResponseMessage都用using包裹,自动完成资源释放和流刷新,保证文件写入完整。
  • File.Create替代File.OpenWrite:直接创建/覆盖文件,彻底避免旧内容干扰。
  • 简化状态码判断:用response.EnsureSuccessStatusCode()替代手动判断,代码更简洁。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 09:25:30