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

C# Azure Function解压HTTP FormFile上传ZIP的实现与方案选型

C# Azure Function 处理ZIP上传解压实现与方案选型

一、HTTP触发函数直接接收FormFile解压存Blob的实现

前置配置

  • 调整函数请求大小限制:Azure Function消费计划默认HTTP请求体上限为100MB,匹配你60-70MB的解压后文件大小,可在host.json中显式配置避免触发413错误:
{
  "version": "2.0",
  "extensions": {
    "http": {
      "maxRequestBodyLength": 104857600
    }
  }
}
  • 引入依赖:直接使用框架内置的System.IO.Compression包处理压缩文件,引入官方Azure.Storage.Blobs包操作Blob存储,无需第三方解压组件。

核心实现逻辑

全程使用流处理,不需要将文件写入函数实例本地磁盘,减少IO开销:

[FunctionName("UploadZipAndUnzip")]
public static async Task<IActionResult> Run(
    [HttpTrigger(AuthorizationLevel.Function, "post")] HttpRequest req,
    ILogger log)
{
    // 读取form-data中上传的ZIP文件,字段名和Postman配置的form-data key保持一致
    var zipFile = req.Form.Files.GetFile("zipFile");
    if (zipFile == null || zipFile.Length == 0)
    {
        return new BadRequestObjectResult("未检测到有效ZIP上传文件");
    }

    // 初始化目标Blob容器客户端
    var storageConnStr = Environment.GetEnvironmentVariable("AzureWebJobsStorage");
    var blobServiceClient = new BlobServiceClient(storageConnStr);
    var targetContainer = blobServiceClient.GetBlobContainerClient("unzipped-target");
    await targetContainer.CreateIfNotExistsAsync(Azure.Storage.Blobs.Models.PublicAccessType.None);

    // 直接读取上传流解压,全程不落盘
    using var zipReadStream = zipFile.OpenReadStream();
    using var zipArchive = new ZipArchive(zipReadStream, ZipArchiveMode.Read);
    foreach (var entry in zipArchive.Entries)
    {
        // 跳过目录类空条目
        if (entry.FullName.EndsWith('/') || entry.Length == 0) continue;

        // *必须做文件名安全校验,防范Zip Slip路径遍历攻击*
        // 过滤条目中的../等相对路径字符,避免文件写入非预期路径
        var safeFileName = Path.GetFileName(entry.FullName);
        var blobClient = targetContainer.GetBlobClient(safeFileName);

        // 单文件流直接写入Blob
        await using var entryStream = entry.Open();
        await blobClient.UploadAsync(entryStream, overwrite: true);
    }

    return new OkObjectResult("文件上传解压完成");
}

Postman测试注意点

  • 请求类型选POST,Body选form-data,新增File类型字段,key和代码中读取的字段名一致(示例中为zipFile),选择本地ZIP文件即可。
  • 不要手动添加Content-Type请求头,Postman会自动生成带boundary的multipart/form-data头,手动配置会导致请求解析失败。

二、两种技术方案选型对比

方案1:HTTP触发直接解压

  • 优势:链路短,无额外原始ZIP存储开销,少一次Blob读写和函数触发流程,端到端耗时更短;接口返回时解压流程已完成,前端不需要额外轮询处理状态,实现逻辑简单。
  • 劣势:请求处理耗时和文件大小、解压速度绑定,大文件场景容易触发函数超时(消费计划最长可配置超时为10分钟);无原始ZIP留存,解压失败需要用户重新上传,无重试依据。

方案2:先存原始ZIP,Blob触发函数异步解压

  • 优势:HTTP函数仅负责文件转存,逻辑极轻响应快,几乎不会超时;原始ZIP文件持久化留存,解压失败可基于原文件重试,配合Blob触发的内置重试机制可靠性更高;上传和解压流程解耦,就算解压服务异常,用户上传操作不会失败。
  • 劣势:多一份原始ZIP的存储成本(按你70MB解压后大小计算,ZIP压缩后体积约20-40MB,存储成本可忽略);链路更长,接口返回时解压未完成,前端如果需要感知解压结果需要额外开发状态查询接口。

选型建议

你当前场景解压后总大小仅60-70MB,单请求解压耗时普遍在数秒级别,远低于HTTP函数超时阈值,优先选择HTTP触发直接解压方案即可,整体资源消耗远低于你的预估——流处理模式下内存占用不会超过文件体积,也没有额外磁盘IO开销,完全适配消费计划的资源配额。
只有后续业务扩展到单文件解压后体积超过500MB、解压耗时超过1分钟,或者有原始文件留存审计需求时,再切换为Blob触发的异步解压方案即可。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 13:06:24