ZipUtil.py 3.9 KB
# coding=utf-8
#author:        4N
#createtime:    2021/5/24
#email:         nheweijun@sina.com

import zipfile
import os
import uuid

class ZipUtil:

    @classmethod
    def unzip(cls,zip_file,create_uuid=False):
        '''
        
        :param zip_file: 待解压文件
        :return: 压缩文件路径
        '''

        #处理zip
        #存储路径
        if create_uuid:
            store_path = os.path.join(os.path.dirname(zip_file),uuid.uuid1().__str__())
        else:
            store_path =os.path.dirname(zip_file)
        zip_file = zipfile.ZipFile(zip_file, 'r')

        #是否要重命名文件夹,解压中文压缩文件和内嵌中文压缩文件,需要重命名文件夹
        rename_path = False
        rename_path_origin=None
        rename_path_after =None

        for names in zip_file.namelist():
            #zipfile解压中文文件会有编码问题,需要解压后重命名,因为zipfile内部使用的是cp437
            try:
                name_t = names.encode('cp437').decode('gbk')
            except:
                name_t = names.encode('utf-8').decode('utf-8')

            zip_file.extract(names,store_path)

            os.chdir(store_path)  # 切换到目标目录

            
            if names.__contains__("/"):
                pat = names.split("/")
                pat_t = name_t.split("/")[-1]
                pat[-1] = pat_t
                name_tt = "/".join(pat)
                # 只重命名文件
                os.rename(names, name_tt)
                
                if not names[-1].__eq__("/"):
                    rename_path = True
                    rename_path_origin = names.split("/")[:-1]
                    rename_path_after = name_t.split("/")[:-1]
            else:

                os.rename(names, name_t)  # 重命名文件
                
        # 重命名文件夹
        if rename_path:
            for i in range(len(rename_path_origin),0,-1):
                origin = "/".join(rename_path_origin[:i])
                rename_path_origin[i-1] = rename_path_after[i-1]
                after = "/".join(rename_path_origin[:i])
                os.rename(origin, after)

        os.chdir(os.path.dirname(store_path))
        zip_file.close()

        return store_path
    
    
    
    
    @classmethod
    def create_zip(cls,path, file_paths:list):
        """
        创建ZIP文件  并写入文件  (支持大文件夹)
        :param path:   创建的ZIP文件路径
        :param file_paths:
        :return:
        """
        try:
            with zipfile.ZipFile(path, 'w', zipfile.ZIP_DEFLATED) as zip:
                for file_path in file_paths:
                    if os.path.isdir(file_path):
                        pre_len = len(os.path.dirname(file_path))
                        for parent, dir_names, file_names in os.walk(file_path):
                            for filename in file_names:
                                path_file = os.path.join(parent, filename)
                                if path_file != path:  # 避免将新创建的zip写入该zip文件
                                    arc_name = path_file[pre_len:].strip(os.path.sep)  # 相对路径  不进行则会生成目录树
                                    zip.write(path_file, arc_name)
                    elif os.path.isfile(file_path):
                        zip.write(file_path, os.path.basename(file_path))
                    else:
                        print("创建zip文件对象失败!原因:未识别到路径")
                        return "创建zip文件对象失败!原因:未识别到路径"
                return True

        except Exception as e:
            print("创建zip文件对象失败!原因:%s" % str(e))
            return "创建zip文件对象失败!原因:%s" % str(e)
        
        return path