web-dev-qa-db-ja.com

Amazon S3のファイルのmd5sumを取得する方法

AmazonのS3に既存のファイルがある場合、ファイルをダウンロードせずにmd5sumを取得する最も簡単な方法は何ですか?

ありがとう

61
Switch

うーん...私はあなたがETagヘッダーを見ることができると思います。 (この場合、GETではなくHTTP [〜#〜] head [〜#〜] メソッドを使用できます。)彼らはそれをはっきりとは言いませんが、AmazonがMD5ハッシュを使用することはほぼ確実ですETagの場合。 PUT Object documentation から(彼らが​​なぜちょうどすぐに出てそれを言うのではないのか):

ネットワーク上でデータが破損しないようにするには、Content-MD5ヘッダーを使用します。 Content-MD5ヘッダーを使用すると、Amazon S3は指定されたMD5値に対してオブジェクトをチェックします。一致しない場合、Amazon S3はエラーを返します。さらに、オブジェクトをAmazon S3に入れながらMD5を計算し、返されたEtagを計算されたMD5値と比較できます。

また、 SOAPメソッド を使用すると、データ自体ではなくメタデータのみを要求できます。

39
Jason S

ETagは、マルチパートアップロードではMD5ではないようです(Gael Fraiteurのコメントによる)。これらの場合、マイナスのサフィックスと数字が含まれます。ただし、マイナスの前のビットでさえ、MD5と同じ長さであっても、MD5のようには見えません。おそらく、接尾辞はアップロードされたパーツの数ですか?

23
Duncan Harris

AWSのETagのドキュメントには次のように書かれています。

エンティティタグはオブジェクトのハッシュです。 ETagは、メタデータではなく、オブジェクトのコンテンツにのみ変更を反映します。 ETagは、オブジェクトデータのMD5ダイジェストである場合とそうでない場合があります。それがそうであるかどうかは、オブジェクトがどのように作成されたか、および以下で説明するようにどのように暗号化されるかによって異なります。

  • PUTオブジェクト、POSTオブジェクト、またはコピー操作、またはAWSマネジメントコンソールを介して作成され、SSE-S3またはプレーンテキストによって暗号化されたオブジェクトには、オブジェクトのMD5ダイジェストであるETagがありますデータ。
  • PUTオブジェクト、POSTオブジェクト、またはコピー操作、またはAWSマネジメントコンソールを介して作成され、SSE-CまたはSSE-KMSによって暗号化されたオブジェクトは、MD5ダイジェストではないETagを持っていますオブジェクトデータの。
  • オブジェクトがMultipart UploadまたはPart Copy操作のいずれかによって作成された場合、暗号化の方法に関係なく、ETagはMD5ダイジェストではありません。

リファレンス: http://docs.aws.Amazon.com/AmazonS3/latest/API/RESTCommonResponseHeaders.html

21
Dennis Wu

Md5がS3のETagと同じではない理由を調べるために時間をかけて探索する人のために。

ETagはデータのチャックに対して計算し、すべてのmd5hashを連結してmd5ハッシュを再度作成し、最後にチャンクの数を保持します。

ハッシュを生成するC#バージョンです

    string etag = HashOf("file.txt",8);

ソースコード

    private string HashOf(string filename,int chunkSizeInMb)
    {
        string returnMD5 = string.Empty;
        int chunkSize = chunkSizeInMb * 1024 * 1024;

        using (var crypto = new MD5CryptoServiceProvider())
        {
            int hashLength = crypto.HashSize/8;

            using (var stream = File.OpenRead(filename))
            {
                if (stream.Length > chunkSize)
                {
                    int chunkCount = (int)Math.Ceiling((double)stream.Length/(double)chunkSize);

                    byte[] hash = new byte[chunkCount*hashLength];
                    Stream hashStream = new MemoryStream(hash);

                    long nByteLeftToRead = stream.Length;
                    while (nByteLeftToRead > 0)
                    {
                        int nByteCurrentRead = (int)Math.Min(nByteLeftToRead, chunkSize);
                        byte[] buffer = new byte[nByteCurrentRead];
                        nByteLeftToRead -= stream.Read(buffer, 0, nByteCurrentRead);

                        byte[] tmpHash = crypto.ComputeHash(buffer);

                        hashStream.Write(tmpHash, 0, hashLength);

                    }

                    returnMD5 = BitConverter.ToString(crypto.ComputeHash(hash)).Replace("-", string.Empty).ToLower()+"-"+ chunkCount;
                }
                else {
                    returnMD5 = BitConverter.ToString(crypto.ComputeHash(stream)).Replace("-", string.Empty).ToLower();

                }
                stream.Close();
            }
        }
        return returnMD5;
    }
4

S3cmdには、lsコマンドで使用できる--list-md5オプションがあることがわかりました。

s3cmd ls --list-md5 s3://bucket_of_mine/

お役に立てれば。

1
ahnkle

これは私のために動作します。 PHPでは、次を使用してローカルファイルとAmazonファイルのチェックサムを比較できます。



    // get localfile md5
    $checksum_local_file = md5_file ( '/home/file' );

    // compare checksum between localfile and s3file    
    public function compareChecksumFile($file_s3, $checksum_local_file) {

        $Connection = new AmazonS3 ();
        $bucket = Amazon_bucket;
        $header = $Connection->get_object_headers( $bucket, $file_s3 );

        // get header
        if (empty ( $header ) || ! is_object ( $header )) {
            throw new RuntimeException('checksum error');
        }
        $head = $header->header;
        if (empty ( $head ) || !is_array($head)) {
            throw new RuntimeException('checksum error');
        }
        // get etag (md5 Amazon)
        $etag = $head['etag'];
        if (empty ( $etag )) {
            throw new RuntimeException('checksum error');
        }
        // remove quotes
        $checksumS3 = str_replace('"', '', $etag);

        // compare md5
        if ($checksum_local_file === $checksumS3) {
            return TRUE;
        } else {
            return FALSE;
        }
    }

0

Jets3tと管理コンソールをアップロードされたファイルのMD5sumに対してクロスチェックしましたが、ETagはMD5sumと等しいようです。 AWS管理コンソールでファイルのプロパティを表示できます。

https://console.aws.Amazon.com/s3/home

0
b10y

PowerShellでc#から変換されたオブジェクトのS3 ETagを取得するコードを次に示します。

function Get-ETag {
  [CmdletBinding()]
  param(
    [Parameter(Mandatory=$true)]
    [string]$Path,
    [Parameter(Mandatory=$true)]
    [int]$ChunkSizeInMb
  )

  $returnMD5 = [string]::Empty
  [int]$chunkSize = $ChunkSizeInMb * [Math]::Pow(2, 20)

  $crypto = New-Object System.Security.Cryptography.MD5CryptoServiceProvider
  [int]$hashLength = $crypto.HashSize / 8

  $stream = [System.IO.File]::OpenRead($Path)

  if($stream.Length -gt $chunkSize) {
    $chunkCount = [int][Math]::Ceiling([double]$stream.Length / [double]$chunkSize)
    [byte[]]$hash = New-Object byte[]($chunkCount * $hashLength)
    $hashStream = New-Object System.IO.MemoryStream(,$hash)
    [long]$numBytesLeftToRead = $stream.Length
    while($numBytesLeftToRead -gt 0) {
      $numBytesCurrentRead = [int][Math]::Min($numBytesLeftToRead, $chunkSize)
      $buffer = New-Object byte[] $numBytesCurrentRead
      $numBytesLeftToRead -= $stream.Read($buffer, 0, $numBytesCurrentRead)
      $tmpHash = $crypto.ComputeHash($buffer)
      $hashStream.Write($tmpHash, 0, $hashLength)
    }
    $returnMD5 = [System.BitConverter]::ToString($crypto.ComputeHash($hash)).Replace("-", "").ToLower() + "-" + $chunkCount
  }
  else {
    $returnMD5 = [System.BitConverter]::ToString($crypto.ComputeHash($stream)).Replace("-", "").ToLower()
  }

  $stream.Close()  
  $returnMD5
}
0
Andrew Marwood