如何下载、然后存档并将zip发送给用户而不将数据存储在RAM和内存中?

问题描述 投票:0回答:1

我需要通过HttpClient从S3下载照片,然后将其存档为zip而不压缩,并将存档发送给用户。但是,我无法将 zip 存储在 RAM 中,也无法创建临时文件,因为我需要创建非常大的档案(15-20 GB 的数据)。

我需要 C# ASP 解决方案。

我试过这个:

var response = HttpContext.Response;
        response.ContentType = "application/octet-stream";
        response.Headers.Add($"Content-Disposition", $"attachment; filename=\"ololo.zip\"");

        await using var outputStream = response.Body;

        using var zipStream = new ZipOutputStream(outputStream);
        zipStream.SetLevel(9);

        for (int i = 0; i < fileUrls.Count; i++)
        {
            var fileName = $"file{i + 1}.jpg";
            var zipEntry = new ZipEntry(fileName);
            zipStream.PutNextEntry(zipEntry);

            using var httpClient = new HttpClient();
            using var remoteStream = await httpClient.GetStreamAsync(fileUrls[i]);

            await remoteStream.CopyToAsync(zipStream);
            zipStream.CloseEntry();
        }

        zipStream.IsStreamOwner = false;
        await zipStream.FinishAsync(default);

        return new EmptyResult();

但是我在异步操作时遇到了错误。我尝试过这个:

[HttpPost]
public async Task Zip([FromBody] JsonToZipInput input)
{        
  Response.ContentType = "application/octet-stream";
  Response.Headers.Add($"Content-Disposition", $"attachment; filename=\"{input.FileName}\"");

  await Response.StartAsync();
    
  using var zipArchive = new ZipArchive(Response.BodyWriter.AsStream(), ZipArchiveMode.Create);
  foreach (var (key, value) in input.FilePathsToUrls)
  {
    var zipEntry = zipArchive.CreateEntry(key, CompressionLevel.Optimal);
    await using var zipStream = zipEntry.Open();
    await using var stream = await _httpClient.GetStreamAsync(value);
    await stream.CopyToAsync(zipStream);
  }
}

但它会将所有存档加载到 RAM 中。

asp.net async-await zip bigdata
1个回答
0
投票

你必须在这里自己动手。您需要遵循 PKWare 应用说明 以及 zip 规范。您可以查看 C 语言的 zipflow 来获取指导。或者您可以尝试将 zipflow 转换为 C#。 zipflow 流式传输 zip 文件,而无需将整个文件存储在内存或文件系统中。

© www.soinside.com 2019 - 2024. All rights reserved.