Skip to content

Instantly share code, notes, and snippets.

@yuki2006
Last active October 14, 2015 05:01
Show Gist options
  • Save yuki2006/74a7396f88988e4a44b1 to your computer and use it in GitHub Desktop.
Save yuki2006/74a7396f88988e4a44b1 to your computer and use it in GitHub Desktop.
Goでファイルをzip圧縮したときにタイムスタンプがずれる問題の回避策 ref: http://qiita.com/yuki2006/items/0211421792bd788f8153
t = t.In(time.UTC)
buf := new(bytes.Buffer)
zw := zip.NewWriter(buf)
if ferr := ZipDir(zw, "zip_dir", "dir"); ferr != nil {
panic(ferr)
}
if ferr := zw.Close(); ferr != nil {
panic(ferr)
}
//zipPathは、zip上で表現されるパスを指定します。
//targetDirは、圧縮するファイルシステム上のディレクトリのパスを指定します。
func ZipDir(writer *zip.Writer, zipPath string, targetDir string) error {
//圧縮するディレクトリをオープンします。
dir, err := os.Open(targetDir)
if err != nil {
return err
}
defer dir.Close()
//ディレクトリ内のファイル一覧を取得します。
files, err := dir.Readdirnames(-1)
if err != nil {
return err
}
for _, fname := range files {
if err := ZipFile(writer, zipPath+"/"+fname, targetDir+"/"+fname); err != nil {
return err
}
}
return nil
}
buf := new(bytes.Buffer)
zw := zip.NewWriter(buf)
if ferr := ZipFile(zw, "zip_path", "file.txt"); ferr != nil {
panic(ferr)
}
if ferr := zw.Close(); ferr != nil {
panic(ferr)
}
//ファイルをzip圧縮します。
//zipPathは、zip上で表現されるパスを指定します。
//targetFileは、圧縮するファイルシステム上のファイルのパスを指定します。
func ZipFile(writer *zip.Writer, zipPath string, targetFile string) error {
f, err := os.Open(targetFile)
if err != nil {
return err
}
defer f.Close()
body, err := ioutil.ReadAll(f)
if err != nil {
return err
}
info , err := os.Stat(targetFile)
if err != nil {
return err
}
header, _ := zip.FileInfoHeader(info)
//zip用のパスを設定
//これを設定しないと、zip内でディレクトリの中に作られない。
header.Name = zipPath
zf, err := writer.CreateHeader(header)
if err != nil {
return err
}
if _, err := zf.Write(body); err != nil {
return err
}
return nil
}
header, _ := FileInfoHeader(info)
//zip用のパスを設定
//これを設定しないと、zip内でディレクトリの中に作られない。
header.Name = zipPath
func FileInfoHeader(fi os.FileInfo) (*zip.FileHeader, error) {
size := fi.Size()
fh := &zip.FileHeader{
Name: fi.Name(),
UncompressedSize64: uint64(size),
}
// 現在のLocalを取得する。
local := time.Now().Local()
//時刻のoffset(秒)を取得する。
_, offset := local.Zone()
//ファイルスタンプの時間に時差分を追加する。
fh.SetModTime(fi.ModTime().Add(time.Duration(offset) * time.Second))
fh.SetMode(fi.Mode())
var uintmax = uint32((1 << 32) - 1)
if fh.UncompressedSize64 > uint64(uintmax) {
fh.UncompressedSize = uintmax
} else {
fh.UncompressedSize = uint32(fh.UncompressedSize64)
}
return fh, nil
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment