Golang如何用zip包实现文件压缩解压工具

来源:AI视频音频作者:仓本头衔:网络博主
导读:本期聚焦于小伙伴创作的《Golang如何用zip包实现文件压缩解压工具》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《Golang如何用zip包实现文件压缩解压工具》有用,将其分享出去将是对创作者最好的鼓励。

在Go语言的标准库中,archive/zip包提供了对zip格式文件的完整读写支持,开发者可以直接基于该包实现文件压缩和解压功能,无需引入第三方依赖,既降低了项目依赖复杂度,也能保证功能的稳定性。无论是日常的文件批量处理工具,还是服务端的上传文件解压需求,都可以通过该包快速实现。

环境准备

本文的示例基于Go 1.18及以上版本,无需额外安装第三方包,直接使用标准库即可。需要引入的包如下:

import (
    "archive/zip"
    "io"
    "os"
    "path/filepath"
    "strings"
)

实现文件压缩功能

压缩单个文件

压缩单个文件的核心逻辑是创建zip文件写入器,将目标文件的内容读取后写入zip条目中。具体实现代码如下:

// CompressSingleFile 压缩单个文件到目标zip路径
func CompressSingleFile(srcFile string, destZip string) error {
    // 创建目标zip文件
    zipFile, err := os.Create(destZip)
    if err != nil {
        return err
    }
    defer zipFile.Close()

    // 创建zip写入器
    zipWriter := zip.NewWriter(zipFile)
    defer zipWriter.Close()

    // 打开源文件
    src, err := os.Open(srcFile)
    if err != nil {
        return err
    }
    defer src.Close()

    // 获取文件信息,用于设置zip条目的属性
    fileInfo, err := src.Stat()
    if err != nil {
        return err
    }

    // 创建zip条目
    header, err := zip.FileInfoHeader(fileInfo)
    if err != nil {
        return err
    }
    // 设置压缩方法为默认压缩
    header.Method = zip.Deflate
    // 条目名称使用文件名,避免路径问题
    header.Name = filepath.Base(srcFile)

    writer, err := zipWriter.CreateHeader(header)
    if err != nil {
        return err
    }

    // 将源文件内容拷贝到zip条目中
    _, err = io.Copy(writer, src)
    return err
}

压缩整个目录

压缩目录需要遍历目录下的所有文件和子目录,逐个将文件添加到zip中,同时需要保持原有的目录结构。实现代码如下:

// CompressDir 压缩整个目录到目标zip路径
func CompressDir(srcDir string, destZip string) error {
    zipFile, err := os.Create(destZip)
    if err != nil {
        return err
    }
    defer zipFile.Close()

    zipWriter := zip.NewWriter(zipFile)
    defer zipWriter.Close()

    // 获取源目录的绝对路径,用于处理相对路径
    absSrcDir, err := filepath.Abs(srcDir)
    if err != nil {
        return err
    }

    // 遍历目录
    err = filepath.Walk(absSrcDir, func(path string, info os.FileInfo, err error) error {
        if err != nil {
            return err
        }
        // 跳过目录本身,只处理文件
        if info.IsDir() {
            return nil
        }

        // 计算zip条目中的相对路径
        relPath, err := filepath.Rel(absSrcDir, path)
        if err != nil {
            return err
        }
        // 替换路径分隔符为zip标准的正斜杠
        relPath = strings.ReplaceAll(relPath, string(os.PathSeparator), "/")

        // 创建zip条目
        header, err := zip.FileInfoHeader(info)
        if err != nil {
            return err
        }
        header.Name = relPath
        header.Method = zip.Deflate

        writer, err := zipWriter.CreateHeader(header)
        if err != nil {
            return err
        }

        // 打开当前文件并拷贝内容
        src, err := os.Open(path)
        if err != nil {
            return err
        }
        defer src.Close()

        _, err = io.Copy(writer, src)
        return err
    })

    return err
}

实现文件解压功能

解压zip文件的核心是读取zip文件中的条目,逐个将条目内容写入到目标目录中,同时需要创建对应的目录结构。实现代码如下:

// DecompressZip 解压zip文件到目标目录
func DecompressZip(zipPath string, destDir string) error {
    // 打开zip文件
    zipReader, err := zip.OpenReader(zipPath)
    if err != nil {
        return err
    }
    defer zipReader.Close()

    // 确保目标目录存在
    err = os.MkdirAll(destDir, 0755)
    if err != nil {
        return err
    }

    // 遍历zip中的所有条目
    for _, file := range zipReader.File {
        // 构建目标路径
        destPath := filepath.Join(destDir, file.Name)
        // 防止路径穿越攻击,检查目标路径是否在destDir下
        if !strings.HasPrefix(destPath, filepath.Clean(destDir)+string(os.PathSeparator)) {
            return errors.New("非法的zip条目路径")
        }

        // 如果是目录,创建目录
        if file.FileInfo().IsDir() {
            err = os.MkdirAll(destPath, file.Mode())
            if err != nil {
                return err
            }
            continue
        }

        // 创建文件所在的目录
        err = os.MkdirAll(filepath.Dir(destPath), 0755)
        if err != nil {
            return err
        }

        // 打开zip条目
        srcFile, err := file.Open()
        if err != nil {
            return err
        }

        // 创建目标文件
        destFile, err := os.OpenFile(destPath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, file.Mode())
        if err != nil {
            srcFile.Close()
            return err
        }

        // 拷贝内容
        _, err = io.Copy(destFile, srcFile)
        destFile.Close()
        srcFile.Close()
        if err != nil {
            return err
        }
    }

    return nil
}

功能测试

可以编写简单的测试代码验证上述功能是否正确:

func main() {
    // 测试压缩单个文件
    err := CompressSingleFile("./test.txt", "./single.zip")
    if err != nil {
        panic(err)
    }

    // 测试压缩目录
    err = CompressDir("./test_dir", "./dir.zip")
    if err != nil {
        panic(err)
    }

    // 测试解压文件
    err = DecompressZip("./dir.zip", "./unzip_dir")
    if err != nil {
        panic(err)
    }
}

注意事项

  • 处理中文文件名时,zip包默认使用UTF-8编码,若遇到其他编码的zip文件可能需要额外处理编码转换。
  • 解压时需要校验条目路径,避免路径穿越导致文件被写入到预期之外的目录,引发安全问题。
  • 压缩大文件时建议添加进度处理逻辑,避免用户等待时无反馈。
  • 操作完成后及时关闭文件句柄,避免资源泄露。

Golangzip包文件压缩文件解压修改时间:2026-06-22 08:00:52

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。