You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Python从application/octet-stream类型的疑似Zip文件恢复数据?

数据恢复可行性分析与编程方案

问题原因分析

你得到的application/octet-stream类型文件,大概率是压缩过程异常中断、工具故障导致的损坏文件——要么是未生成正确压缩结构的残次品,要么是源文件数据直接被拼接成了一个无索引的大文件(因为大小和源文件夹一致,完全没压缩的可能性很高)。

编程恢复的可行路径

1. 先检测文件真实结构

首先通过文件头签名判断文件本质,不同格式有固定的开头字节:

  • ZIP压缩包:50 4B 03 04
  • 7z压缩包:37 7A BC AF 27 1C
  • RAR压缩包:52 61 72 21 1A 07 00
  • JPG图片:FF D8 FF
  • PDF文档:25 50 44 46(即%PDF)
  • DOCX/XLSX:50 4B 03 04(和ZIP一致,因为是压缩格式)

用Python脚本读取文件头验证:

with open("backup.zip", "rb") as f:
    # 读取前8字节转十六进制
    header_hex = f.read(8).hex().upper()
    print(f"文件头十六进制: {header_hex}")

如果检测到对应压缩格式的签名,说明是扩展名错误或损坏的压缩包;如果是图片/文档的签名,说明源文件被直接拼接了。

2. 针对损坏压缩包的恢复

如果是ZIP格式损坏:

  • 尝试用第三方库ziprepair修复:
    from ziprepair import repair_zip
    
    # 复制原文件到backup_repaired.zip再操作
    repair_result = repair_zip("backup.zip", "backup_repaired.zip")
    if repair_result.success:
        print("修复成功,尝试用zipfile读取修复后的文件")
        import zipfile
        with zipfile.ZipFile("backup_repaired.zip", "r") as zf:
            print(zf.namelist())
    else:
        print(f"修复失败: {repair_result.error_message}")
    
  • 如果修复失败,可以手动定位ZIP的中央目录(位于文件末尾,签名50 4B 05 06),提取目录信息后逐个恢复文件,但这个过程需要熟悉ZIP格式规范,实现起来较复杂。

3. 针对源文件拼接的恢复

如果文件是多个源文件直接拼接的(无压缩结构),可以通过扫描文件签名来分割提取:
以下是提取JPG和PDF的示例脚本:

import os

# 定义要识别的文件类型签名
file_signatures = {
    ".jpg": b"\xFF\xD8\xFF",
    ".pdf": b"%PDF"
}

output_dir = "recovered_files"
os.makedirs(output_dir, exist_ok=True)

with open("backup.zip", "rb") as f:
    file_data = f.read()

current_pos = 0
file_count = 0

while current_pos < len(file_data):
    # 遍历所有签名,查找匹配的位置
    matched_ext = None
    match_pos = len(file_data)
    for ext, sig in file_signatures.items():
        pos = file_data.find(sig, current_pos)
        if pos != -1 and pos < match_pos:
            match_pos = pos
            matched_ext = ext
    
    if matched_ext is None:
        # 没有找到更多签名,结束
        break
    
    # 如果当前位置和匹配位置有间隔,跳过无效数据
    if match_pos > current_pos:
        current_pos = match_pos
    
    # 查找下一个签名的位置,作为当前文件的结束
    next_pos = len(file_data)
    for ext, sig in file_signatures.items():
        pos = file_data.find(sig, current_pos + len(sig))
        if pos != -1 and pos < next_pos:
            next_pos = pos
    
    # 提取当前文件数据
    file_content = file_data[current_pos:next_pos]
    file_name = f"recovered_{file_count}{matched_ext}"
    with open(os.path.join(output_dir, file_name), "wb") as out_f:
        out_f.write(file_content)
    
    print(f"已提取: {file_name}")
    file_count += 1
    current_pos = next_pos

print(f"提取完成,共恢复{file_count}个文件")

注意:这种方法对无明显签名的纯文本文件效果差,且可能出现文件截断或合并的情况,需要手动验证恢复的文件完整性。

关键注意事项

  • 绝对不要修改原始文件,所有操作都在复制的副本上进行,避免二次损坏。
  • 50GB文件处理耗时较长,建议在性能较好的机器上运行脚本,且确保有足够的存储空间存放恢复的文件。

内容的提问来源于stack exchange,提问作者user19192927

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 17:25:26