C# 在Web API响应中将zip文件添加为内容下载时文件大小加倍
我正在将zip文件保存到AWS S3存储桶中。我现在正在尝试创建一个C#.NET API,该API允许我从bucket下载指定的密钥,并将其保存到内容密钥中的HttpResponseMessage 我参考了以下问题来设置我对zip文件的响应: 我已经修改了前一个问题中的代码,以便它从TransferUtility流读取 问题是,我在尝试提取或查看文件时出错,如下所示: 我从API得到的响应如下所示: 相关代码如下所示: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
[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的流不是问题所在
我在这个项目的任何地方都找不到任何关于“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);