C# 在Web API响应中将zip文件添加为内容下载时文件大小加倍

C# 在Web API响应中将zip文件添加为内容下载时文件大小加倍,c#,amazon-web-services,amazon-s3,webapi,C#,Amazon Web Services,Amazon S3,Webapi,我正在将zip文件保存到AWS S3存储桶中。我现在正在尝试创建一个C#.NET API,该API允许我从bucket下载指定的密钥,并将其保存到内容密钥中的HttpResponseMessage 我参考了以下问题来设置我对zip文件的响应: 我已经修改了前一个问题中的代码,以便它从TransferUtility流读取 问题是,我在尝试提取或查看文件时出错,如下所示: 我从API得到的响应如下所示: 相关代码如下所示: [HttpGet, Route("GetFileFromS3B

我正在将zip文件保存到AWS S3存储桶中。我现在正在尝试创建一个C#.NET API,该API允许我从bucket下载指定的密钥,并将其保存到内容密钥中的HttpResponseMessage

我参考了以下问题来设置我对zip文件的响应:

我已经修改了前一个问题中的代码,以便它从TransferUtility流读取

问题是,我在尝试提取或查看文件时出错,如下所示:

我从API得到的响应如下所示:

相关代码如下所示:

[HttpGet, Route("GetFileFromS3Bucket")]
public HttpResponseMessage GetFileFromS3Bucket(string keyName)
{
    HttpResponseMessage response = new HttpResponseMessage();
    string bucketName = "myBucket";
    RegionEndpoint bucketRegion = RegionEndpoint.ARegion;
    IAmazonS3 s3Client;
    s3Client = new AmazonS3Client(bucketRegion);

    try
    {
        var fileTransferUtility = new TransferUtility(s3Client);
        var stream = fileTransferUtility.OpenStream(bucketName, keyName);
        response.Content = new StreamContent(stream);
        response.Content.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment");
        response.Content.Headers.ContentDisposition.FileName = keyName + ".zip";
        response.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/zip");
        response.StatusCode = HttpStatusCode.OK;
    }
    catch (Exception e)
    {
        response.Content = new StringContent("Something went wrong, error: " + e.Message);
        response.StatusCode = HttpStatusCode.InternalServerError;
    }

    return response;
}
故障排除的结果:

  • 基于S3,来自WebAPI的文件的大小几乎是预期大小的两倍。这在不同的文件中是一致的
  • 将bucket更改为可公开访问没有帮助(设置已恢复为不允许公开访问)
  • 将文件类型更改为XML不会显示格式良好的错误(有人建议,如果S3提供了错误,您可能会收到XML响应)
  • 将S3流保存到一个文件中,然后直接保存到一个文件中,可以得到正确的文件大小。可以肯定地说,来自S3的流不是问题所在
HTTPResponseMessage处理zip文件的方式似乎有问题。我不确定它是在服务器端,还是在客户端解析数据,而Swagger根本无法做到这一点。任何帮助都将不胜感激

更新1 我不相信这个字符串是Base64编码的,因为我将流转换为字符串的结果如下:

我已经用两行代码更新了代码示例,其中显示了从流到字符串的转换

更新2 我已经确认了问题在于响应如何处理流,或者响应本身中的某些内容。从S3下载文件流并保存到本地计算机上的一个新文件中,生成了一个按预期打开的有效文件

更新3 链接到带有测试文件的GDrive文件夹: 很遗憾,我无法提供对原始文件的访问,因为它包含敏感数据。但是,提供的文件仍然会导致相同的问题。 有趣的是,测试文件看起来像:

文件名两边的下划线都很奇怪

我正在运行以下相关软件包:

更新4 我在各种文件中发现了以下UTF8引用:

文件:configuration91.svcinfo


我在这个项目的任何地方都找不到任何关于“responseEncoding”的内容。

我要给出一个答案,因为发生在你身上的事情是非正统的。我在很多事情上使用S3,并且在过去做过您正在做的事情,没有任何问题。为了确保我在模仿您正在做的事情,我复制了您的代码:

[HttpGet, Route("GetFileFromS3Bucket/{keyName}")]
public HttpResponseMessage GetFileFromS3Bucket(string keyName)
{
    string bucketName = "testzipfilesagain";
    string awsAccessKey = "AKIAJ********A3QHOUA";
    string awsSecretKey = "IYUJ9Gy2wFCQ************dCq5suFS";

    IAmazonS3 client = new AmazonS3Client(awsAccessKey, awsSecretKey, RegionEndpoint.USEast1);

    var fileTransferUtility = new TransferUtility(client);
    var stream = fileTransferUtility.OpenStream(bucketName, "md5.zip");

    var resp = new HttpResponseMessage();

    resp.Content = new StreamContent(stream);
    resp.Content.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment");
    resp.Content.Headers.ContentDisposition.FileName = keyName + ".zip";
    resp.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/zip");
    resp.StatusCode = HttpStatusCode.OK;

    return resp;
}
以下是我安装的软件包:

  <ItemGroup>
    <PackageReference Include="AWSSDK.S3" Version="3.3.111.37" />
    <PackageReference Include="Microsoft.AspNetCore.Mvc.WebApiCompatShim" Version="2.2.0" />
    <PackageReference Include="Swashbuckle.AspNetCore" Version="5.5.1" />
  </ItemGroup>
结果如下:


我将做一些研究,找出是什么导致您的流被UTF-8编码。你的配置文件中有没有这样的东西?您可以在整个解决方案中搜索类似于“utf”或“utf8”或“utf-8”的内容吗?

看起来fie是GZIP或Base64字符串。这两个文件都比原始文件大,因为二进制文件被压缩成可读的ASCII字符。@jdweng这会导致文件损坏吗?如果是这样,我如何确保S3(或Web API的输出,我不确定它将在何处中断)的.zip格式是我希望在响应内容中提供的格式?如果您得到的是Base64字符串,则需要使用byte[]data=Convert.FromBase64String(string)然后将字节以二进制形式保存到文件中。@jdweng为回答干杯,我已经做了一些测试,并确认返回的数据既不是GZIP也不是Base64字符串。我有点担心AWS库处理数据的方式可能有问题。如果你使用一个小的zip,比如5KB的zip,它的大小是否仍然是原来的两倍?如果你能做到这一点,那么把原始的zip文件和一个“大小加倍”的zip文件一起发布,我很确定我可以告诉你出了什么问题。嗨,安迪,谢谢你的回答,我现在将解决所有这些问题,并让你知道结果。非常感谢,我很高兴有人喜欢配置方面的东西,我讨厌它,因为我倾向于寻找新的方法来解决这些问题:1。Nugets已经过时了,我要走了。然而,这并没有解决问题2。没有。我实际上没有startup.cs,因为我没有运行.NET Core(如果我完全误解了这一点,请纠正我)4。我很快会让你知道结果的。这个链接看起来很有前途!出于兴趣,你是如何发现它们是UTF8编码的?只是想知道我自己将来的故障排除。此外,文件最初的编码是什么?我将看看是否有一种方法可以强制对给定内容的编码类型进行编码HttpResponseMessage@Stevo--我在一个十六进制编辑器中打开它,看到文件中的字节
0xef 0xbf 0xbd
序列是UTF-8令牌。无论如何,你真的应该在你的解决方案中搜索字符串“utf-8”,看看配置中是否出现了任何问题。哦,对不起,我更新了我的问题,但忘了提及它。请参见更新4中的图像和注释
    var goodBytes = File.ReadAllBytes("Some test to upload to S3.zip");
    var badBytes = File.ReadAllBytes("_Some test to upload to S3.zip.zip_");

    File.WriteAllText("Some test to upload to S3.zip.utf8", Encoding.UTF8.GetString(goodBytes));
    var utf8EncodedGoodBytes = File.ReadAllBytes("Some test to upload to S3.zip.utf8");

    var identical = badBytes.SequenceEqual(utf8EncodedGoodBytes);