-
Notifications
You must be signed in to change notification settings - Fork 823
/
util.go
141 lines (125 loc) · 2.57 KB
/
util.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
package utils
import (
"archive/tar"
"compress/gzip"
"errors"
"fmt"
"io"
"net/http"
"os"
"path/filepath"
"time"
)
// Downloader Download progress
type Downloader struct {
io.Reader
Total int64
Current int64
}
// Read Implementation of Downloader
func (d *Downloader) Read(p []byte) (n int, err error) {
n, err = d.Reader.Read(p)
if err != nil {
if err != io.EOF {
return
}
fmt.Println("\nDownload complete.")
return
}
d.Current += int64(n)
fmt.Printf("\rDownloading...[ %.2f%% ]", float64(d.Current*10000/d.Total)/100)
return
}
// DownloadFile Download files via URL
func DownloadFile(url, filePath string) error {
httpClient := http.Client{
Timeout: 60 * time.Second,
}
resp, err := httpClient.Get(url)
if err != nil {
return err
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return fmt.Errorf("failed download file. url: %s code: %v", url, resp.StatusCode)
}
file, err := os.Create(filePath)
if err != nil {
return err
}
defer file.Close()
downloader := &Downloader{
Reader: resp.Body,
Total: resp.ContentLength,
}
if _, err := io.Copy(file, downloader); err != nil {
return err
}
return nil
}
// DeCompress decompress tar.gz
func DeCompress(file, targetPath string) error {
r, err := os.Open(file)
if err != nil {
return err
}
defer r.Close()
gr, err := gzip.NewReader(r)
if err != nil {
return fmt.Errorf("new reader failed. %v", err)
}
defer gr.Close()
tr := tar.NewReader(gr)
for {
header, err := tr.Next()
if errors.Is(err, io.EOF) {
break
}
if err != nil {
return err
}
switch header.Typeflag {
case tar.TypeDir:
if err := os.Mkdir(targetPath+"/"+header.Name, 0755); err != nil {
return err
}
case tar.TypeReg:
outFile, err := os.Create(targetPath + "/" + header.Name)
if err != nil {
return err
}
if err := ioCopyN(outFile, tr); err != nil {
return err
}
outFile.Close()
default:
fmt.Printf("uknown type: %v in %s\n", header.Typeflag, header.Name)
}
}
return nil
}
// ioCopyN fix Potential DoS vulnerability via decompression bomb.
func ioCopyN(outFile *os.File, tr *tar.Reader) error {
for {
if _, err := io.CopyN(outFile, tr, 1024); err != nil {
if errors.Is(err, io.EOF) {
break
}
return err
}
}
return nil
}
// ListFiles traverse directory files
func ListFiles(path string) []string {
var files []string
if err := filepath.Walk(path, func(path string, info os.FileInfo, err error) error {
if !info.IsDir() {
files = append(files, path)
}
return nil
}); err != nil {
fmt.Println(err)
}
return files
}