zipfile.BadZipfile: File name in directory "AndroidManifest.xml" and header "META-INF/MANIFEST.MF" d

问题

python 使用zipfile库来解压apk压缩文件的时候,出现了报错zipfile.BadZipfile: File name in directory "AndroidManifest.xml" and header "META-INF/MANIFEST.MF" differ.

剖析问题

根据异常日志,

File “c:\Python27\lib\zipfile.py”, line 1028, in extract
return self._extract_member(member, path, pwd)
File “c:\Python27\lib\zipfile.py”, line 1082, in _extract_member
with self.open(member, pwd=pwd) as source,
File “c:\Python27\lib\zipfile.py”, line 980, in open
zinfo.orig_filename, fname)
zipfile.BadZipfile: File name in directory “AndroidManifest.xml” and header “META-INF/MANIFEST.MF” differ.

抛出异常的地方是:c:\Python27\lib\zipfile.py", line 980,我们去代码处看看,到底干了什么?
从下面代码可以看出,这是个打开压缩文件的函数,找准关键点fname != zinfo.orig_filename这两个变量是关键,fname = zef_file.read(fheader[_FH_FILENAME_LENGTH]) 这个语句大致可以从命名看出是读取文件头一定偏移处的内容,大概。zinfo.orig_filename这个是zipinfo对象的文件名,也就是我想提取出来的文件名称,是zipinfo对象的一个属性,也就是可能是文件头一定偏移处的内容和要提取的文件名对比,出现的不同

    def open(self, name, mode="r", pwd=None):
        """Return file-like object for 'name'."""
        if mode not in ("r", "U", "rU"):
            raise RuntimeError, 'open() requires mode "r", "U", or "rU"'
        if not self.fp:
            raise RuntimeError, \
                  "Attempt to read ZIP archive that was already closed"

        # Only open a new file for instances where we were not
        # given a file object in the constructor
        if self._filePassed:
            zef_file = self.fp
            should_close = False
        else:
            zef_file = open(self.filename, 'rb')
            should_close = True

        try:
            # Make sure we have an info object
            if isinstance(name, ZipInfo):
                # 'name' is already an info object
                zinfo = name
            else:
                # Get info object for name
                zinfo = self.getinfo(name)

            zef_file.seek(zinfo.header_offset, 0)

            # Skip the file header:
            fheader = zef_file.read(sizeFileHeader)
            if len(fheader) != sizeFileHeader:
                raise BadZipfile("Truncated file header")
            fheader = struct.unpack(structFileHeader, fheader)
            if fheader[_FH_SIGNATURE] != stringFileHeader:
                raise BadZipfile("Bad magic number for file header")

            fname = zef_file.read(fheader[_FH_FILENAME_LENGTH])
            if fheader[_FH_EXTRA_FIELD_LENGTH]:
                zef_file.read(fheader[_FH_EXTRA_FIELD_LENGTH])

            if fname != zinfo.orig_filename:
                raise BadZipfile, \
                        'File name in directory "%s" and header "%s" differ.' % (
                            zinfo.orig_filename, fname)

为了确认上面的分析的正确性,我们看看这个zip包的文件结构
出现报错的zip文件结构
下面是一个可以使用zipfile提取文件的压缩包的文件结构,我们对比一下,可以看出确实是文件头这块除了问题。然后尝试提取这个有出现问题zip包的其他文件,是可以提取的

解决方法

上面这个问题的解决方法我自己没有找到办法,如果有大佬知道,欢迎评论。
暂时使用别的方法来替代这个zipfile压缩库,我选择的是使用java 写一个jar解压工具,使用流的方式来解压缩

简书:代码位置

猜你喜欢

转载自blog.csdn.net/github_38641765/article/details/84978070