Определение Etag изменилось в Amazon S3 - PullRequest
49 голосов
/ 06 июля 2011

Некоторое время я немного использовал Amazon S3 для резервного копирования.Обычно после загрузки файла я проверяю совпадения сумм MD5, чтобы убедиться, что я сделал хорошую резервную копию.S3 имеет заголовок "etag", который использовался для получения этой суммы.

Однако, когда я недавно загрузил большой файл, Etag больше не кажется суммой md5.Он содержит дополнительные цифры и дефис "696df35ad1161afbeb6ea667e5dd5dab-2861".Я не могу найти документацию об этом изменении.Я проверил, используя консоль управления S3 и Cyberduck.

Я не могу найти документацию об этом изменении.Есть указатели?

Ответы [ 15 ]

0 голосов
/ 04 февраля 2019

Я основывался на ответе r03 и здесь для этого есть отдельная утилита Go: https://github.com/lambfrier/calc_s3_etag

Пример использования:

$ dd if=/dev/zero bs=1M count=10 of=10M_file
$ calc_s3_etag 10M_file
669fdad9e309b552f1e9cf7b489c1f73-2
$ calc_s3_etag -chunksize=15 10M_file
9fbaeee0ccc66f9a8e3d3641dca37281-1
0 голосов
/ 12 сентября 2018

Улучшение ответа @ Spedge's и @ Rob. Вот функция python3 md5, которая принимает файловую форму и не зависит от возможности получить размер файла с помощью os.path.getsize.

# Function : md5sum
# Purpose : Get the md5 hash of a file stored in S3
# Returns : Returns the md5 hash that will match the ETag in S3
# https://github.com/boto/boto3/blob/0cc6042615fd44c6822bd5be5a4019d0901e5dd2/boto3/s3/transfer.py#L169
def md5sum(file_like,
           multipart_threshold=8 * 1024 * 1024,
           multipart_chunksize=8 * 1024 * 1024):
    md5hash = hashlib.md5()
    file_like.seek(0)
    filesize = 0
    block_count = 0
    md5string = b''
    for block in iter(lambda: file_like.read(multipart_chunksize), b''):
        md5hash = hashlib.md5()
        md5hash.update(block)
        md5string += md5hash.digest()
        filesize += len(block)
        block_count += 1

    if filesize > multipart_threshold:
        md5hash = hashlib.md5()
        md5hash.update(md5string)
        md5hash = md5hash.hexdigest() + "-" + str(block_count)
    else:
        md5hash = md5hash.hexdigest()

    file_like.seek(0)
    return md5hash
0 голосов
/ 13 апреля 2016

Вот версия 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;
    }
0 голосов
/ 09 сентября 2015

Пример с Python отлично работает, но при работе с Bamboo они устанавливают размер части в 5 МБ, что НЕ СТАНДАРТНО !!(s3cmd - 15 МБ) Также отрегулировано для использования 1024 для вычисления байтов.

Пересмотрено для работы с репозиториями бамбукового артефакта s3.

import hashlib
import binascii


# Max size in bytes before uploading in parts. 
AWS_UPLOAD_MAX_SIZE = 20 * 1024 * 1024
# Size of parts when uploading in parts
AWS_UPLOAD_PART_SIZE = 5 * 1024 * 1024

#
# Function : md5sum
# Purpose : Get the md5 hash of a file stored in S3
# Returns : Returns the md5 hash that will match the ETag in S3
def md5sum(sourcePath):

    filesize = os.path.getsize(sourcePath)
    hash = hashlib.md5()

    if filesize > AWS_UPLOAD_MAX_SIZE:

        block_count = 0
        md5string = ""
        with open(sourcePath, "rb") as f:
            for block in iter(lambda: f.read(AWS_UPLOAD_PART_SIZE), ""):
                hash = hashlib.md5()
                hash.update(block)
                md5string = md5string + binascii.unhexlify(hash.hexdigest())
                block_count += 1

        hash = hashlib.md5()
        hash.update(md5string)
        return hash.hexdigest() + "-" + str(block_count)

    else:
        with open(sourcePath, "rb") as f:
            for block in iter(lambda: f.read(AWS_UPLOAD_PART_SIZE), ""):
                hash.update(block)
        return hash.hexdigest()
0 голосов
/ 19 февраля 2014

Конечно, многократная загрузка файлов может быть распространенной проблемой. В моем случае я обслуживал статические файлы через S3, и файл etag .js отличался от локального файла, даже если его содержимое было таким же.

Оказывается, что даже если содержание было одинаковым, это было потому, что окончания строк были разными. Я исправил окончания строк в своем git-репозитории, загрузил измененные файлы в S3, и теперь он работает нормально.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...