Last active
August 11, 2017 21:09
-
-
Save guitarrapc/f10b5fbceee6861b34373cd54bfbbe01 to your computer and use it in GitHub Desktop.
S3 Multipart ETag Calculation for C#. Refer : https://stackoverflow.com/questions/12186993/what-is-the-algorithm-to-compute-the-amazon-s3-etag-for-a-file-larger-than-5gb#answer-19896823
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
void Main() | |
{ | |
var file = @"YOUR TARGET FILE"; | |
var bytes = FileHashes.GetFileBinary(file); | |
var multipartETag = FileHashes.CalculateMultipartEtag(bytes, 16); | |
multipartETag.Dump(); | |
} | |
public static byte[] GetHash(this byte[] array, HashAlgorithm algorithm) | |
{ | |
var hash = algorithm.ComputeHash(array); | |
return hash; | |
} | |
public static string CalculateMultipartEtag(byte[] array, int chunkCount) | |
{ | |
var multipartSplitCount = 0; | |
var chunkSize = 1024 * 1024 * chunkCount; | |
var splitCount = array.Length / chunkSize; | |
var mod = array.Length - chunkSize * splitCount; | |
IEnumerable<byte> concatHash = new byte[] {}; | |
using (var md5 = MD5.Create()) | |
{ | |
for (var i = 0; i < splitCount; i++) | |
{ | |
var offset = i == 0 ? 0 : chunkSize * i; | |
var chunk = GetSegment(array, offset, chunkSize); | |
var hash = chunk.ToArray().GetHash(md5); | |
concatHash = concatHash.Concat(hash); | |
multipartSplitCount++; | |
} | |
if (mod != 0) | |
{ | |
var chunk = GetSegment(array, chunkSize * splitCount, mod); | |
var hash = chunk.ToArray().GetHash(md5); | |
concatHash = concatHash.Concat(hash); | |
multipartSplitCount++; | |
} | |
var multipartHash = concatHash.ToArray().GetHash(md5).ToHexString(); | |
return multipartHash + "-" + multipartSplitCount; | |
} | |
} | |
private static ArraySegment<T> GetSegment<T>(this T[] array, int offset, int? count = null) | |
{ | |
if (count == null) { count = array.Length - offset; } | |
return new ArraySegment<T>(array, offset, count.Value); | |
} | |
public static string ToHashString(this byte[] hash) | |
{ | |
return BitConverter.ToString(hash).Replace("-", "").ToLower(); | |
} | |
public static string ToHexString(this byte[] bytes) | |
{ | |
var chars = new char[bytes.Length * 2 + 2]; | |
for (int i = 0; i < bytes.Length; i++) | |
{ | |
chars[2 * i + 2] = ToHexDigit(bytes[i] / 16); | |
chars[2 * i + 3] = ToHexDigit(bytes[i] % 16); | |
} | |
return new string(chars).ToLower(); | |
} | |
private static char ToHexDigit(int i) | |
{ | |
if (i < 10) | |
{ | |
return (char)(i + '0'); | |
} | |
return (char)(i - 10 + 'A'); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment