2 回答
![?](http://img1.sycdn.imooc.com/533e4d5b0001d57502200203-100-100.jpg)
TA贡献1850条经验 获得超11个赞
要手动执行此操作,您可以修改上面链接的代码:
ExampleZipWriter
给你一个简单的例子,它有很多缺陷,但可能很容易理解:
func ZipWriter() {
baseFolder := "/Users/tom/Desktop/testing/"
// Get a Buffer to Write To
outFile, err := os.Create(`/Users/tom/Desktop/zip.zip`)
if err != nil {
fmt.Println(err)
}
defer outFile.Close()
// Create a new zip archive.
w := zip.NewWriter(outFile)
// Add some files to the archive.
addFiles(w, baseFolder, "")
if err != nil {
fmt.Println(err)
}
// Make sure to check the error on Close.
err = w.Close()
if err != nil {
fmt.Println(err)
}
}
我们也使用它来递归地迭代文件以生成文件夹:
func addFiles(w *zip.Writer, basePath, baseInZip string) {
// Open the Directory
files, err := ioutil.ReadDir(basePath)
if err != nil {
fmt.Println(err)
}
for _, file := range files {
fmt.Println(basePath + file.Name())
if !file.IsDir() {
dat, err := ioutil.ReadFile(basePath + file.Name())
if err != nil {
fmt.Println(err)
}
// Add some files to the archive.
f, err := w.Create(baseInZip + file.Name())
if err != nil {
fmt.Println(err)
}
_, err = f.Write(dat)
if err != nil {
fmt.Println(err)
}
} else if file.IsDir() {
// Recurse
newBase := basePath + file.Name() + "/"
fmt.Println("Recursing and Adding SubDir: " + file.Name())
fmt.Println("Recursing and Adding SubDir: " + newBase)
addFiles(w, newBase, baseInZip + file.Name() + "/")
}
}
}
![?](http://img1.sycdn.imooc.com/5333a1d100010c2602000200-100-100.jpg)
TA贡献1831条经验 获得超10个赞
这是使用 Go 的内置递归文件遍历器的解决方案,因为到目前为止的最佳答案已经实现了他们自己的文件遍历器:
除此之外,我今天在生成 zip 文件时发现的一些发现可能会让其他人头疼:
to 的参数不
w.Create(zippath)
应该以“/”开头,并且应该相对于 zip 根目录(也就是解压缩存档时创建的文件夹)。所以一个顶级的“manifest.xml”文件应该是w.Create("manifest.xml")
. 嵌套文件应该是w.Create("a/b/c.css)
. 如果您正在生成不良/令人惊讶的档案,请先检查以确保您没有违反此规则。我的代码不会尝试强制执行此操作。一些规范(如 epub)希望文件按特定顺序排列,但 Go
filepath.Walk
会按词汇顺序爬行。(就此而言,我发现到目前为止,从 Calibre 到 macOS 上的 Books.app,所有 epub 解析器都很宽松)。如果您需要特定的顺序,那么@LeTigre 的解决方案ReadDir
可以让您在每个下降级别对文件进行排序。
package main
import (
"archive/zip"
"fmt"
"io"
"os"
"path/filepath"
)
// Zips "./input" into "./output.zip"
func main() {
file, err := os.Create("output.zip")
if err != nil {
panic(err)
}
defer file.Close()
w := zip.NewWriter(file)
defer w.Close()
walker := func(path string, info os.FileInfo, err error) error {
fmt.Printf("Crawling: %#v\n", path)
if err != nil {
return err
}
if info.IsDir() {
return nil
}
file, err := os.Open(path)
if err != nil {
return err
}
defer file.Close()
// Ensure that `path` is not absolute; it should not start with "/".
// This snippet happens to work because I don't use
// absolute paths, but ensure your real-world code
// transforms path into a zip-root relative path.
f, err := w.Create(path)
if err != nil {
return err
}
_, err = io.Copy(f, file)
if err != nil {
return err
}
return nil
}
err = filepath.Walk("input", walker)
if err != nil {
panic(err)
}
}
- 2 回答
- 0 关注
- 269 浏览
添加回答
举报