/
unzip.go
132 lines (109 loc) · 3.37 KB
/
unzip.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
package befiles
import (
"archive/zip"
"fmt"
"io"
"os"
"path/filepath"
"strings"
)
// Unzip un-zip the file in src to destination path
func Unzip(src string, destination string) ([]FileData, error) {
// a variable that will store any
//file names available in a array of strings
var filenames []FileData
// OpenReader will open the Zip file
// specified by name and return a ReadCloser
// Readcloser closes the Zip file,
// rendering it unusable for I/O
// It returns two values:
// 1. a pointer value to ReadCloser
// 2. an error message (if any)
r, err := zip.OpenReader(src)
// if there is any error then
// (err!=nil) becomes true
if err != nil {
// and this block will break the loop
// and return filenames gathered so far
// with an err message, and move
// back to the main function
return filenames, err
}
defer r.Close()
// defer makes sure the file is closed
// at the end of the program no matter what.
for _, f := range r.File {
// this loop will run until there are
// files in the source directory & will
// keep storing the filenames and then
// extracts into destination folder until an err arises
// Store "path/filename" for returning and using later on
fpath := filepath.Join(destination, f.Name)
// Checking for any invalid file paths
if !strings.HasPrefix(fpath, filepath.Clean(destination)+string(os.PathSeparator)) {
return filenames, fmt.Errorf("%s is an illegal filepath", fpath)
}
if f.FileInfo().IsDir() {
// Creating a new Folder
os.MkdirAll(fpath, os.ModePerm)
continue
}
// Creating the files in the target directory
if err = os.MkdirAll(filepath.Dir(fpath), os.ModePerm); err != nil {
return filenames, err
}
// The created file will be stored in
// outFile with permissions to write &/or truncate
outFile, err := os.OpenFile(fpath,
os.O_WRONLY|os.O_CREATE|os.O_TRUNC,
f.Mode())
// again if there is any error this block
// will be executed and process
// will return to main function
if err != nil {
// with filenames gathered so far
// and err message
return filenames, err
}
rc, err := f.Open()
// again if there is any error this block
// will be executed and process
// will return to main function
if err != nil {
// with filenames gathered so far
// and err message back to main function
return filenames, err
}
_, err = io.Copy(outFile, rc)
// Close the file without defer so that
// it closes the outfile before the loop
// moves to the next iteration. this kinda
// saves an iteration of memory & time in
// the worst case scenario.
outFile.Close()
rc.Close()
// the filename that is accessed is now appended
// into the filenames string array with its path
fd, err := ReadFileInfo(fpath)
if err != nil {
return nil, err
}
filenames = append(filenames, *fd)
// again if there is any error this block
// will be executed and process
// will return to main function
if err != nil {
// with filenames gathered so far
// and err message back to main function
return filenames, err
}
}
// Finally after every file has been appended
// into the filenames string[] and all the
// files have been extracted into the
// target directory, we return filenames
// and nil as error value as the process executed
// successfully without any errors*
// *only if it reaches until here.
return filenames, nil
}