为什么哈希在API调用中为输入文件创建的每个新临时文件都考虑相同的值?

时间:2018-04-29 15:21:19

标签: python flask

我有一个API调用,它从表单中获取文件输入,并为创建的临时文件生成哈希键。但是当再次选择不同的文件作为输入文件时,会生成相同的哈希.API调用的代码片段如下:(排除其他不相关的代码)

 def gen_hash():
     for attr, document in request.files.iteritems():
            orig_filename = document.filename
            new_doc = add_doc(orig_filename, orig_filename)
            #mhash = None
            ##############
            # hashing algorithm checks the contents of the file if
            # modified before uploading to destination, NOT file name
            try:
                tmp1 = tempfile.NamedTemporaryFile(delete=False)
                tmp1.write(document.read())
                tmp1.seek(0)
                # for chunk in iter(lambda: tmp1.read(128* sha1().block_size),
                #                   b""):
                for chunk in iter(lambda: tmp1.read(128), b""):
                    sha1().update(chunk)
                mhash1 = sha1().hexdigest()
                print mhash1
            finally:
                #print e
                os.unlink(tmp1.name) 

使用flask v.0.12,python 2.7。为什么不同文件内容的哈希键相同?

1 个答案:

答案 0 :(得分:1)

hashlib.sha1()创建一个SHA-1哈希对象,您可以使用数据进行更新,最后获取摘要。但是你没有保存那个对象。为每个块创建并丢弃一个新对象,然后创建另一个空摘要并获取其值。您始终要对相同的空序列进行哈希处理并获取da39a3ee5e6b4b0d3255bfef95601890afd80709

由于您在单个read中获取整个文档,因此将其写入临时文件并进行分块读取没有任何好处。只需哈希你抓取的数据。

def gen_hash():
    for attr, document in request.files.iteritems():
        orig_filename = document.filename
        new_doc = add_doc(orig_filename, orig_filename)
        mhash1 = sha1(document.read()).hexdigest()
        print mhash1

假设document是一个类似于对象的文件,您可以更新块中的哈希值,并避免一次读取整个文档的内存成本。

def gen_hash():
    for attr, document in request.files.iteritems():
        orig_filename = document.filename
        new_doc = add_doc(orig_filename, orig_filename)
        hash = sha1()
        for chunk in iter(lambda: document.read(65536), ''):
            hash.update(chunk)
        mhash1 = hash.hexdigest()
        print mhash1

当使用2个参数调用iter时,第一个是生成数据的函数,第二个是迭代的结束条件。因此,iter(lambda: document.read(65536), '')会一直调用从document读取数据的函数,直到没有任何内容为止。