【问题标题】:Chunk a file into variable sized read in python在python中将文件分块为可变大小的读取
【发布时间】:2020-05-23 18:22:49
【问题描述】:

我正在尝试以不同大小的块读取文件以计算文件 etag 并与 s3 资源上的 etag 进行比较。

我意识到这是一个以前被问过的问题,但我看到的所有答案都涉及通过处理保持一致的甚至大小的分块。

我想要做的是获取任何大小的文件,对于该文件的前 5GB,计算每个 5MB 块的 md5。然后对于接下来的 25GB 文件,计算每个 25MB 块的 md5。对于文件的最终数量,计算每个 125MB 块的 md5。

我认为这可以归结为: 1000 个 5MB 到 5GB 的块 接下来 1000 个 25MB 到 25GB 的块(或读取到 30GB) 最后 8000 个 125MB 的块,每个块高达 1TB

S3 协议将块数限制为最大 10000。

所以对于一个 49.9 GB 的文件,我最终会连接 2136 个部分并计算 md5。

原因是上传到 s3 设备是使用基于此分块方案上传的 Goofys 完成的。

我尝试使用嵌套的 while 循环(我的条件没有按预期工作),而我目前的尝试是使用 if 语句...

我迷路的地方是确保 file.read(chunk_size) 在达到大小阈值时发生变化,直到读取整个文件。

【问题讨论】:

    标签: python-3.x amazon-s3


    【解决方案1】:

    原来我的假设很糟糕,解决方案比我想象的要容易。我太难了。

    也就是说,请随时提供反馈以改进代码。

    这是我的解决方案:

    import os, hashlib
    from hashlib import md5
    
    def etag_calc(inputfile):
    
        md5_digest = []
        partsize1 = 5*1024*1024
        partsize2 = 25*1024*1024
        partsize3 = 125*1024*1024
    
        with open(inputfile, 'rb') as f:
            for chunk in iter(lambda: f.read(partsize1), b''):
                md5_digest.append(hashlib.md5(chunk).digest())
                if len(md5_digest) < 1000:
                    continue
                else:
                    break
    
            for chunk in iter(lambda: f.read(partsize2), b''):
                md5_digest.append(hashlib.md5(chunk).digest())
                if len(md5_digest) < 2000:
                    continue
                else:
                    break
    
            for chunk in iter(lambda: f.read(partsize3), b''):
                md5_digest.append(hashlib.md5(chunk).digest())
                if len(md5_digest) < 10000:
                    continue
                else:
                    break
    
        return hashlib.md5(b''.join(md5_digest)).hexdigest() + '-' + str(len(md5_digest))
    

    【讨论】:

    • 谢谢约翰。我发现我今天发的很糟糕,我只是没有时间更正它。我必须更正的代码还有另一个问题,即
    【解决方案2】:

    S3 实际上存储带有在上传期间创建的标头的部分,包括 ETag。您可以使用 HeadObject 中未记录的 x-amz-mp-parts-count 标头,然后在 GetObject 期间使用其他未记录的 partNumber 标头下载每​​个部分。下载所有部分后,您可以通过hashlib.md5(b''.join(md5_digest)).hexdigest() + '-' + str(len(md5_digest)) 计算组合哈希。无论哪个客户端创建了对象,此技术都将起作用。参考:

    https://github.com/gaul/undocumented-s3-apis#get-object-by-multipart-number

    【讨论】:

    • 这非常有帮助。非常感谢
    猜你喜欢
    • 2011-06-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-08-19
    • 1970-01-01
    • 2019-03-12
    • 2015-10-14
    • 1970-01-01
    相关资源
    最近更新 更多