zipfile 中文文件名 解压乱码

上传文件功能模块需求及BUG现象:

环境

mac

django 1.11.13

python 3.6

功能需求:

上传一个.zip格式的压缩文件

解压该test.zip压缩文件

解压zip文件时,遍历其目录下所有子文件,同时计算出单个子文件的有效代码行数

这时,发现解压后的子文件名中文出现乱码,如下图:

BUG截图

解决思路

1、解压过程中,发现解压的文件内容正常;

2、使用的是第三方库zipfile模块,因为第1步得到正常的文件内容,本地业务逻辑可先不排查;

3、首先检查zipfile的源码中,针对编码/解码的执行过程仔细排查发现:

zipfile中根据文件 flag 检测的时候,只支持 cp437 和 utf-8

找到下面两处,并追加修正后,乱码现象解决:(追加的decode编码可根据实际情况修改,如win环境下乱码采用.decode('gbk')

# zipfile.py

# 第一处
if flags & 0x800:
# UTF-8 file names extension
filename = filename.decode('utf-8')
else:
# Historical ZIP filename encoding
filename = filename.decode('cp437')
# 追加此句
filename = filename.encode("cp437").decode('utf-8') # 第二处
if zinfo.flag_bits & 0x800:
# UTF-8 filename
fname_str = fname.decode("utf-8")
else:
fname_str = fname.decode("cp437")
# 追加此句
fname_str = fname_str.encode("cp437").decode('utf-8')

解决后,正常显示:


上传功能源码

import zipfile

# 指定想要统计的文件类型
whitelist = ['py'] # 遍历文件, 递归遍历文件夹中的所有
def getFile(basedir):

# 存储上传解压后的文件列表
    filelists = []
for parent, dirnames, filenames in os.walk(basedir):
# for dirname in dirnames:
# getFile(os.path.join(parent,dirname)) #递归
for filename in filenames:
ext = filename.split('.')[-1]
# 只统计指定的文件类型,略过一些log和cache文件
if ext in whitelist:
filelists.append(os.path.join(parent, filename)) # 统计一个文件的行数
def countLine(fname):
count = 0
single_quotes_flag = False
double_quotes_flag = False
with open(fname, 'rb') as f:
for file_line in f:
file_line = file_line.strip()
# print(file_line)
# 空行
if file_line == b'':
pass # 注释 # 开头
elif file_line.startswith(b'#'):
pass # 注释 单引号 ''' 开头
elif file_line.startswith(b"'''") and not single_quotes_flag:
single_quotes_flag = True
# 注释 中间 和 ''' 结尾
elif single_quotes_flag == True:
if file_line.endswith(b"'''"):
single_quotes_flag = False # 注释 双引号 """ 开头
elif file_line.startswith(b'"""') and not double_quotes_flag:
double_quotes_flag = True
# 注释 中间 和 """ 结尾
elif double_quotes_flag == True:
if (file_line.endswith(b'"""')):
double_quotes_flag = False # 代码
else:
count += 1 # print(fname + '----', count)
# 单个文件行数
print(fname, '----count:', count)
return count def un_zip(file_name):
"""unzip zip file"""
zip_file = zipfile.ZipFile(file_name)
# <zipfile.ZipFile filename='/Users/limengjie/Desktop/pyhon/SMS0614/upload_file/0617.zip' mode='r'>
if os.path.isdir(file_name + "_files"):
pass
else:
os.mkdir(file_name + "_files")
for names in zip_file.namelist():
zip_file.extract(names, file_name + "_files/")
# 遍历解压后得到的文件夹, 递归遍历文件夹中的所有子文件
getFile(file_name + "_files")
totalline = 0
# 遍历解压后的文件列表,统计单个文件的行数并汇总
for filelist in filelists:
totalline = totalline + countLine(filelist)
zip_file.close()
# 返回上传文件所有子文件的总行数
return totalline

补充:上传业务逻辑代码

class Uploading(View):

    def get(self, request):
return render(request, "uploading.html", ) def post(self, request):
# 1、拿到压缩文件对象file_obj
file_obj = request.FILES.get("user_file")
file_name = os.path.join(file_dir, file_obj.name)
file_size = file_obj.size
with open(file_name, "wb") as f:
for line in file_obj.chunks():
f.write(line) # 2、解压压缩文件,并获取代码行数属性
total_line = un_zip(file_name)
# 3、单个文件进行文件对象实例化,文件名,文件大小,代码行数
models.FileObj.objects.create(
fileName=file_obj.name,
fileSize=file_size,
fileLineCount=total_line
)
return redirect("/upload_file/")

优化需求

统计行数优化:mac环境解压文件时,系统会自动追加__MACOSX文件夹,为了不遍历此文件夹,需补充:

在getFIle函数中修改,即可:

# MAC环境下略过__MACOSX文件夹
if "__MACOSX" in dirnames:
pop_index = dirnames.index("__MACOSX")
dirnames.pop(pop_index)

优化后,得到我们需要的结果:

(完)

zipfile 解压文件名乱码的更多相关文章

  1. Windows 压缩文件到 Linux中解压文件名乱码

    问题 在Windows中将文件夹压缩后,拿到Ubuntu系统中解压,中文文件名乱码 解决 因为两个系统所使用的编码不同,Windows一般使用GBK编码,Ubuntu使用utf8编码,只需要在解压的时 ...

  2. python使用zipfile解压中文乱码问题

    在zipfile.ZipFile中获得的filename有中日文则很大可能是乱码,这是因为 在zip标准中,对文件名的 encoding 用的不是 unicode,而可能是各种软件根据系统的默认字符集 ...

  3. 关于zipfile解压出现的字符编码问题

    使用zipfile解压文件时,出现了中文乱码问题,具体解决方法有两个,直接上代码吧. def deco_zip(path, file_path): os.mkdir(file_path) # 方式一 ...

  4. Java中解压文件名有中文的rar包出现乱码问题的解决

    import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import j ...

  5. Net Core解决ZipFile解压中文出现乱码

    一.在main方法中添加 Encoding.RegisterProvider(CodePagesEncodingProvider.Instance); 二.解压添加 //sourceArchiveFi ...

  6. linux ubuntu12.04 解压中文zip文件,解压之后乱码

    在windows下压缩后的zip包,在ubuntu下解压后显示为乱码问题 1.zip文件解压之后文件名乱码: 第一步 首先安装7zip和convmv(如果之前没有安装的话) 在命令行执行安装命令如下: ...

  7. 通过zipfile解压指定目录下的zip文件

    代码: # -*- coding: utf-8 -*- import os import zipfile import platform import multiprocessing # 解压后的文件 ...

  8. ubuntu rar文件解压中文乱码问题

    http://blog.csdn.net/android_huber/article/details/7382867 前段时间经常要在ubuntu系统中去解压rar的文件,但是每次解压出来却总是出现中 ...

  9. unzip解压中文乱码

    1 问题描述 直接 unzip xxx.zip 乱码,肯定是编码问题了不用问.但是unzip没有指定编码的选项: 网上的解决方案如下: unzip -O GBK/GB18030CP936 xx.zip ...

随机推荐

  1. SQL Join 语句

    SQL Join 语句 SQL 中每一种连接操作都包括一个连接类型和连接条件. 连接类型 决定了如何处理连接条件不匹配的记录. 连接类型 返回结果 inner join 只包含左右表中满足连接条件的记 ...

  2. 11.1NOIP模拟赛解题报告

    心路历程 预计得分:\(100 + 100 + 50\) 实际得分:\(100 + 100 + 50\) 感觉老师找的题有点水呀. 上来看T1,woc?裸的等比数列求和?然而我不会公式呀..感觉要凉 ...

  3. typeof的探讨

    console.log(typeof 'abc') // "string" console.log(typeof true )// "boolean" cons ...

  4. Express (Routing、Middleware、托管静态文件、view engine 等等)

    1. Express 简介 Express 是基于 Node.js 平台,快速.开放.极简的 web 开发框架,它提供一系列强大的特性,帮助你创建各种 Web 和移动设备应用. Express 不对 ...

  5. php接收post过来的json数据

    <html> <head> <title>json</title> <script src="//cdn.bootcss.com/jqu ...

  6. 04_ActiveMQ事务与三种签收方式

    [ActiveMQ添加事务] 添加事务主要注意两点: 1.修改Session配置,启用事务 /** * 3.通过Connection对象创建Session会话(上下文环境对象),用于接收消息. * 参 ...

  7. Picasso通过URL获取--用户头像的圆形显示

    1.设置布局属性: <ImageView android:scaleType="fitXY"/> 2.BitmapUtils类-- 得到指定圆形的Bitmap对象 pu ...

  8. Vue2.0的动画效果

    本文只是结合一些代码和图片加强对Vue动画的理解,更多资料请戳这里 结合原生CSS实现动画 下面是一张图片,简单清晰明了是吧^-^ 下面是一段代码 <!DOCTYPE html> < ...

  9. 向Github提交更改的代码

    更改了本地的某一文件的代码,那么如何覆盖Github上的同一文件代码呢?请看以下步骤: 1.先用 git status 看你更改了哪些文件: 2.然后 git add 你想要提交的更改的文件 或者 g ...

  10. Mac下终端自动补全功能

    记录一下终端的一些使用命令,跟自动补全的配置,主要怕以后忘记了. 1.终端自动补全的配置 打开终端,输入 : nano .inputrc 在文件里面写上: set completion-ignore- ...