下载到云服务器的文件是否完整?用 Python 标准库做 SHA-256 校验

举报
yd_283252214 发表于 2026/10/15 09:20:18 2026/10/15
【摘要】 使用 Python 标准库分块计算文件 SHA-256,核对云服务器传输前后的内容一致性。包含命令行脚本、退出码、四类边界验证,以及摘要校验的适用边界。

把安装包、模型文件或备份从一台机器传到另一台机器后,文件名相同、大小相近,并不足以说明内容完全一致。一个实用做法是:传输前计算摘要,传输完成后再计算一次,并比较结果。本文给出一个无需第三方依赖的分块读取示例。

1. 分块读取,避免一次读入整个文件

将下面代码保存为 sha256_check.py:

import argparse
import hashlib
import re


def sha256_file(path):
    digest = hashlib.sha256()
    with open(path, "rb") as source:
        for chunk in iter(lambda: source.read(1024 * 1024), b""):
            digest.update(chunk)
    return digest.hexdigest()


def main():
    parser = argparse.ArgumentParser(description="Calculate or verify SHA-256")
    parser.add_argument("path")
    parser.add_argument("--expected", help="Expected SHA-256, 64 hexadecimal characters")
    args = parser.parse_args()
    expected = args.expected.strip().lower() if args.expected else None
    if expected is not None and re.fullmatch(r"[0-9a-f]{64}", expected) is None:
        parser.error("--expected must contain exactly 64 hexadecimal characters")
    try:
        actual = sha256_file(args.path)
    except OSError as error:
        parser.exit(2, f"Cannot read file: {error}\n")
    print(actual)
    if expected is not None:
        if actual != expected:
            parser.exit(1, "SHA-256 mismatch\n")
        print("SHA-256 matches")


if __name__ == "__main__":
    main()

这里使用 rb 模式读取原始字节,避免文本编码和换行转换影响结果。每次只读取 1 MiB;文件更大时,需要的读取次数增加,读取缓冲不会随文件大小无限增长。with 语句负责关闭文件。持续调用同一个摘要对象的 update,即可计算整份文件的摘要,最后用 hexdigest 得到十六进制字符串。接口行为可参阅 Python 标准库官方文档的 hashlib 章节。

2. 传输前后怎样使用

在源机器上计算摘要:

python sha256_check.py "backup.tar.gz"

记录输出的完整 64 位十六进制值。文件传到云服务器后,把该值作为 --expected 参数传入:

python sha256_check.py "backup.tar.gz" --expected 源机器输出的完整SHA256值

上面中文参数是占位说明,执行时必须替换为真实摘要。文件名含空格时保留引号。参数只接收摘要值,不要连同文件名、SHA256= 前缀一起复制。

脚本匹配成功时退出码为 0,内容不匹配时为 1,参数错误或文件无法读取时为 2。因此,它既能人工运行,也适合在传输脚本中作为后续步骤的条件:校验成功后再解压、导入或替换文件。

3. 已验证的边界情况

核心 sha256_file 函数已在 Python 3.13.1 环境中验证以下情况:

  • 空文件:结果为 e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855。
  • 内容恰好为三个字节 abc 的文件:结果为 ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad。
  • 长度为 2 MiB 加 17 字节的文件:分块结果与对同一内容直接计算的摘要一致,覆盖了跨块和末尾不足一块的情形。
  • 不存在的路径:核心函数抛出 FileNotFoundError,由命令行入口统一处理为读文件失败。

注意,abc 后面如果多一个换行,就已经是另一份内容,不应期待得到相同结果。上述验证针对本地文件计算,不代表已验证某种云存储传输链路。

4. 摘要能证明什么

若前后摘要不同,先核对路径、文件版本和下载是否完成,不要直接认定存储设备故障。计算摘要期间也应避免文件继续被写入,否则比较的可能不是同一个稳定版本。

摘要校验用于检查内容一致性,不等于确认发布者身份。如果文件和所谓的正确摘要都来自同一个不可信来源,即使匹配,也不能据此证明文件安全。软件来源可信度还需要结合官方渠道和签名验证判断。

实际工作中,建议将文件名、版本、大小和 SHA-256 一起记录到发布清单,方便之后定位到底传输了哪一个版本。

本文由 AI 辅助整理,核心文件摘要函数已按上述案例执行验证。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。