github.com/binbinly/pkg@v0.0.11-0.20240321014439-f4fbf666eb0f/util/archive/tar.go (about) 1 package archive 2 3 import ( 4 "archive/tar" 5 "bytes" 6 "io" 7 "os" 8 "time" 9 ) 10 11 // 文件类型 12 const ( 13 TypeReg = tar.TypeReg // 普通文件 14 TypeLink = tar.TypeLink // 硬链接 15 TypeSymlink = tar.TypeSymlink // 符号链接 16 TypeChar = tar.TypeChar // 字符节点 17 TypeBlock = tar.TypeBlock // 块节点 18 TypeDir = tar.TypeDir // 目录 19 TypeFifo = tar.TypeFifo // 先进先出队列节点 20 TypeCont = tar.TypeCont // 保留位 21 TypeXHeader = tar.TypeXHeader // 扩展头 22 TypeXGlobalHeader = tar.TypeXGlobalHeader // 全局扩展头 23 TypeGNULongName = tar.TypeGNULongName // 下一个文件记录有个长名字 24 TypeGNULongLink = tar.TypeGNULongLink // 下一个文件记录指向一个具有长名字的文件 25 TypeGNUSparse = tar.TypeGNUSparse // 稀疏文件 26 ) 27 28 // TarWrite 实现了tar格式压缩文件的存取 29 func TarWrite(files []*File) (buf *bytes.Buffer, err error) { 30 buf = new(bytes.Buffer) 31 32 // 初始化writer 33 var tw = tar.NewWriter(buf) 34 defer tw.Close() 35 36 for _, file := range files { 37 38 // 根据结构体的内容实例化一个header 39 hdr := &tar.Header{ 40 Name: file.Name, // 记录头域的文件名 41 Mode: 0600, // 权限和模式位 42 Uid: 0, // 所有者的用户ID 43 Gid: 0, // 所有者的组ID 44 Size: int64(len(file.Body)), // 字节数(长度) 45 ModTime: time.Now(), // 修改时间 46 Typeflag: TypeReg, // 文件类型 47 Linkname: "", // 链接的目标名 48 Uname: "", // 所有者的用户名 49 Gname: "", // 所有者的组名 50 Devmajor: 0, // 字符设备或块设备的major number 51 Devminor: 0, // 字符设备或块设备的minor number 52 AccessTime: time.Now(), // 访问时间 53 ChangeTime: time.Now(), // 状态改变时间 54 } 55 // writer写入header 56 if err = tw.WriteHeader(hdr); err != nil { 57 return nil, err 58 } 59 // writer写入内容 60 if _, err = tw.Write(file.Body); err != nil { 61 return nil, err 62 } 63 } 64 return 65 } 66 67 // TarRead 读取.tar压缩文件 68 func TarRead(path string) ([]*File, error) { 69 70 // 读取文件内容 71 bf, err := os.ReadFile(path) 72 if err != nil { 73 return nil, err 74 } 75 76 // 实例化buffer 77 var readBuf = bytes.NewBuffer(bf) 78 79 // 初始化一个reader去读取tar内容 80 tr := tar.NewReader(readBuf) 81 82 var hdr *tar.Header 83 var b []byte 84 var files []*File 85 // 循环读取多个文件内容 86 for { 87 // 获取单个文件的header信息 88 hdr, err = tr.Next() 89 90 // 所有文件读取完毕 91 if err == io.EOF { 92 break 93 } else if err != nil { 94 return nil, err 95 } 96 97 // 读取数据流信息 98 b, err = io.ReadAll(tr) 99 if err != nil { 100 return nil, err 101 } 102 files = append(files, &File{ 103 Name: hdr.Name, 104 Body: b, 105 }) 106 } 107 return files, nil 108 }