错误地将MemoryStream压缩到S3桶哈希



我试图将对象序列化为JSON (newtonsoft.json),并以gzip压缩形式将其存储在S3桶中。我想使用PutObjectRequest的MD5Digest属性来确认成功传输,但是我在从MemoryStream中正确计算哈希时遇到了麻烦。我猜它与编码有关。

BasicAWSCredentials credentials = new BasicAWSCredentials(<access key>, <secret key>);
AmazonS3Client s3Client = new AmazonS3Client(credentials, <region>);
AmazonS3Client s3Client 
string md5Hash = null;
//Serialize JSON package to be uploaded to AWS
JsonSerializer serializer = new JsonSerializer();
serializer.NullValueHandling = NullValueHandling.Include;
serializer.TypeNameHandling = TypeNameHandling.Auto;
using (MemoryStream memoryStream = new MemoryStream())
{
//Write JSON to memory stream through compression layer
using (GZipStream zipStream = new GZipStream(memoryStream, CompressionLevel.Fastest, true))
using (StreamWriter sw = new StreamWriter(zipStream))
using (JsonWriter writer = new JsonTextWriter(sw))
{
serializer.Serialize(writer, <object to serialize>);
writer.Flush();
}
//Store gzipped JSON package hash to confirm successful upload later
using (MD5 md5 = MD5.Create())
{
byte[] hash = md5.ComputeHash(memoryStream);
md5Hash = string.Concat(hash.Select(x => x.ToString("x2")));
}
//Reset memoryStream to start because ComputeHash has consumed it
memoryStream.Position = 0;
//Upload to AWS
PutObjectRequest request = new PutObjectRequest();
request.InputStream = memoryStream;
request.Key = <file name>;
request.BucketName = <bucket>;
request.ContentType = "application/gzip";
request.MD5Digest = md5Hash;
PutObjectResponse response = s3Client.PutObject(request);
}

在我的例子中有两个问题。

Anon Coward正确地识别出MemoryStream的位置需要重置。

另一个问题是PutObjectRequest。MD5 digest期望base64表示(即使AWS在Etag中将MD5哈希显示为十六进制)。

代码的哈希部分应该是这样的,这两个问题都解决了

memoryStream.Position = 0;
using (MD5 md5 = MD5.Create())
{
byte[] hash = md5.ComputeHash(memoryStream);
md5Hash = Convert.ToBase64String(hash);
}

最新更新