首页 > 解决方案 > 从 S3 下载后生成的 Zip 文件无效

问题描述

我正在创建一个 zip 文件,该文件看起来有效,但在我将其放入 Amazon S3 存储桶后始终无效。我使用 System.IO.Compression 执行任务,使用 AmazonS3Client 上传:

private byte[] GenerateZipFile(string tenant)
{
   byte[] zipData;

   var results = QueryAggregateTable(tenant);
   using (var memoryStream = new MemoryStream())
   using (var archive = new ZipArchive(memoryStream, ZipArchiveMode.Create, true))
   {
      foreach (var item in results)
      {
          var archiveEntry = archive.CreateEntry($"{item.RowKey:D3}.json", CompressionLevel.Fastest);
          using (var entryStream = archiveEntry.Open())
          {
              var entryBytes = Encoding.UTF8.GetBytes(item.Data);
              entryStream.Write(entryBytes, 0, item.Data.Length);
          }
      }

      zipData = memoryStream.ToArray();
   }

   return zipData;
}

private async Task UploadToAmazon(byte[] zipData, string tenant)
{
    var bucketName = _config["egestionBucketName"];
    var configCreds = _config["egestionAwsCredentials"].Split(":");

    var awsCreds = new BasicAWSCredentials(configCreds[0], configCreds[1]);
    var awsRegion = Amazon.RegionEndpoint.GetBySystemName(_config["egestionRegionEndpointSystemName"]);

    var s3Client = new AmazonS3Client(awsCreds, awsRegion);
    using (var stream = new MemoryStream(zipData))
    {
        var putRequest = new PutObjectRequest
        {
            BucketName = bucketName,
            Key = $"{tenant}-{DateTime.UtcNow.ToString("s")}.zip",
            InputStream = stream,
            CannedACL = S3CannedACL.BucketOwnerFullControl
        };

        await s3Client.PutObjectAsync(putRequest);
    }

}

从生成返回后,字节数组看起来不错,实际上上传方法确实将具有正确名称的文件加载到存储桶中。当我尝试下载文件进行检查时,我无法打开它并显示一条消息,指出它无效。

我在 async/await 方面遇到了一些问题,我怀疑它可能是相关的,但我找不到 PutObject 的非异步选项。任何帮助表示赞赏。

标签: c#amazon-s3.net-coreaws-sdk

解决方案


这不是异步等待问题。

在存档有机会将所有数据写入流之前,正在收集内存流中的字节。上传的存档不完整,因此下载时无效。

移动

zipData = memoryStream.ToArray();

到存档using块之外,以便在处置存档时将任何缓冲的数据刷新到支持流。

//...

using (var memoryStream = new MemoryStream()) {
    using (var archive = new ZipArchive(memoryStream, ZipArchiveMode.Create, true)) {
        foreach (var item in results) {
            var archiveEntry = archive.CreateEntry($"{item.RowKey:D3}.json", CompressionLevel.Fastest);
            using (var entryStream = archiveEntry.Open()) {
                var entryBytes = Encoding.UTF8.GetBytes(item.Data);
                entryStream.Write(entryBytes, 0, entryBytes.Length);
            }
        }
    }//Archive disposed and pushed any remaining buffered data to the stream.
    zipData = memoryStream.ToArray();
}

//...

推荐阅读