-
Notifications
You must be signed in to change notification settings - Fork 1
zip 包解压乱码 #127
Open
Labels
Description
zip 包解压乱码
场景
使用 golang zip 包解压时,文件名含有中文会出现乱码.
原因
因为压缩包是在 windows 平台压缩的,压缩软件 winrar 会使用本地编码方式进行压缩,所以含有中文的文件名是 gbk 格式的,
而 golang 字符串是使用 utf-8 格式,从而出现乱码.
解决
通过标识位识别 gbk 编码,若是则转换为 utf-8
如果未设置通用位11,则文件名和注释使用原始的ZIP字符编码
如果设置了通用位11,则文件名和注释必须使用UTF-8存储规范定义的字符编码形式支持Unicode标准版本4.1.0或更高版本
func (tc *TaskController) unzip(fileName string, dst string) (map[string][]string, int, error) { zf, err := zip.OpenReader(fileName) if err != nil { return nil, 0, err } defer zf.Close() total := 0 // 总文件数,记录任务进度 files := make(map[string][]string) // 文件信息缓存,sku => 文件名 for _, file := range zf.File { // 注意,windows 下的压缩文件是GBK,解压可能有中文名,则需要转换为 utf-8 if file.Flags == 0 { i := bytes.NewReader([]byte(file.Name)) decoder := transform.NewReader(i, simplifiedchinese.GB18030.NewDecoder()) content, _ := ioutil.ReadAll(decoder) file.Name = string(content) } path := filepath.Join(dst, file.Name) if file.FileInfo().IsDir() { continue } f, err := file.Open() if err != nil { log.Error("[file.Open] error: %v", err) return nil, 0, err } if err = os.MkdirAll(filepath.Dir(path), os.ModePerm); err != nil { f.Close() return nil, 0, err } fw, err := os.OpenFile(path, os.O_CREATE|os.O_RDWR|os.O_TRUNC, file.Mode()) if err != nil { log.Error("[os.OpenFile] error: %v", err) return nil, 0, err } _, err = io.Copy(fw, f) if err != nil { f.Close() fw.Close() return nil, 0, err } f.Close() fw.Close() sku := tc.getSku(file.Name) if sku == "" { continue } files[sku] = append(files[sku], file.Name) total += 1 } return files, total, nil }
参考
go 处理zip解压时乱码问题
Creating a zip archive with Unicode filenames using Go's archive/zip