【发布时间】:2020-08-03 12:30:01
【问题描述】:
我正在将 zip 文件保存到 AWS S3 存储桶。我现在正在尝试创建一个 C# .NET API,它允许我从存储桶中下载指定的密钥并将其保存到 Content 密钥中的 HttpResponseMessage。
我参考了以下问题来设置我对 zip 文件的回复:How to send a zip file from Web API 2 HttpGet
我已修改上一个问题中的代码,使其改为从 TransferUtility 流中读取。
相关代码如下:
[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;
}
故障排除结果:
- 来自 Web API 的文件的大小几乎是 S3 中预期大小的两倍。这在不同文件中是一致的
- 将存储桶更改为可公开访问没有帮助(设置后恢复为不允许公开访问)
- 将文件类型更改为 XML 未显示格式正确的错误(有一个建议,如果 S3 提供错误,您可能会收到 XML 响应)
- 将 S3 流保存到文件,然后直接保存到文件会产生正确的文件大小。似乎可以肯定地说来自 S3 的流不是问题
HTTPResponseMessage 处理 zip 文件的方式似乎存在问题。我不确定它实际上是在服务器端,还是在客户端来解析数据,而 Swagger 根本无法做到这一点。任何帮助将不胜感激。
更新 1 我不相信这个字符串是 Base64 编码的,因为我将流转换为字符串得到的结果如下:
我已经更新了代码示例,其中两行显示了从流到字符串的转换。
更新 2 我已经确认问题在于响应如何处理流,或者响应本身的某些内容。从 S3 下载文件流并保存到本地计算机上的新文件会生成按预期打开的有效文件。
更新 3 链接到带有测试文件的 GDrive 文件夹:https://drive.google.com/drive/folders/1q_N3NTHz5E_nebtBQJHor3HfqUZWhGgd?usp=sharing 很遗憾,我无法提供对原始文件的访问权限,因为它包含敏感数据。但是,提供的文件仍然会导致相同的问题。 有趣的是,测试文件看起来像:
文件名两边的下划线很奇怪。
我正在运行以下相关软件包:
更新 4 我在各种文件中发现了以下 UTF8 引用:
我在项目的任何地方都找不到任何关于“responseEncoding”的内容。
【问题讨论】:
-
看起来 fie 是 GZIP 或 Base64 字符串。两者都会比原始文件大,因为二进制文件被打包成可读的 ASCII 字符。
-
@jdweng 这会导致文件损坏吗?如果是这样,我如何确保来自 S3(或来自 Web API,我不确定它会在哪里中断)的输出是我希望在我的响应内容中提供的 .zip 格式?
-
如果你得到一个 Base64 字符串,那么你需要使用 byte[] data = Convert.FromBase64String(string) 然后将字节作为二进制文件保存到文件中。
-
@jdweng 为回复干杯,我做了一些测试并确认返回的数据既不是 GZIP 也不是 Base64 字符串。我有点担心 AWS 库处理数据的方式可能存在问题。
-
如果你做一个小压缩包——比如 5KB 压缩包,它的大小还会翻倍吗?如果你能做到这一点,然后将原始 zip 文件与“大小翻倍”的文件一起发布,我很确定我可以告诉你出了什么问题。
标签: c# amazon-web-services amazon-s3 webapi