"Fossies" - the Fresh Open Source Software Archive 
Member "gdrive-2.1.1/drive/upload.go" (28 May 2021, 6395 Bytes) of package /linux/misc/gdrive-2.1.1.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Go source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
1 package drive
2
3 import (
4 "fmt"
5 "google.golang.org/api/drive/v3"
6 "google.golang.org/api/googleapi"
7 "io"
8 "mime"
9 "os"
10 "path/filepath"
11 "time"
12 )
13
14 type UploadArgs struct {
15 Out io.Writer
16 Progress io.Writer
17 Path string
18 Name string
19 Description string
20 Parents []string
21 Mime string
22 Recursive bool
23 Share bool
24 Delete bool
25 ChunkSize int64
26 Timeout time.Duration
27 }
28
29 func (self *Drive) Upload(args UploadArgs) error {
30 if args.ChunkSize > intMax()-1 {
31 return fmt.Errorf("Chunk size is to big, max chunk size for this computer is %d", intMax()-1)
32 }
33
34 // Ensure that none of the parents are sync dirs
35 for _, parent := range args.Parents {
36 isSyncDir, err := self.isSyncFile(parent)
37 if err != nil {
38 return err
39 }
40
41 if isSyncDir {
42 return fmt.Errorf("%s is a sync directory, use 'sync upload' instead", parent)
43 }
44 }
45
46 if args.Recursive {
47 return self.uploadRecursive(args)
48 }
49
50 info, err := os.Stat(args.Path)
51 if err != nil {
52 return fmt.Errorf("Failed stat file: %s", err)
53 }
54
55 if info.IsDir() {
56 return fmt.Errorf("'%s' is a directory, use --recursive to upload directories", info.Name())
57 }
58
59 f, rate, err := self.uploadFile(args)
60 if err != nil {
61 return err
62 }
63 fmt.Fprintf(args.Out, "Uploaded %s at %s/s, total %s\n", f.Id, formatSize(rate, false), formatSize(f.Size, false))
64
65 if args.Share {
66 err = self.shareAnyoneReader(f.Id)
67 if err != nil {
68 return err
69 }
70
71 fmt.Fprintf(args.Out, "File is readable by anyone at %s\n", f.WebContentLink)
72 }
73
74 if args.Delete {
75 err = os.Remove(args.Path)
76 if err != nil {
77 return fmt.Errorf("Failed to delete file: %s", err)
78 }
79 fmt.Fprintf(args.Out, "Removed %s\n", args.Path)
80 }
81
82 return nil
83 }
84
85 func (self *Drive) uploadRecursive(args UploadArgs) error {
86 info, err := os.Stat(args.Path)
87 if err != nil {
88 return fmt.Errorf("Failed stat file: %s", err)
89 }
90
91 if info.IsDir() {
92 args.Name = ""
93 return self.uploadDirectory(args)
94 } else if info.Mode().IsRegular() {
95 _, _, err := self.uploadFile(args)
96 return err
97 }
98
99 return nil
100 }
101
102 func (self *Drive) uploadDirectory(args UploadArgs) error {
103 srcFile, srcFileInfo, err := openFile(args.Path)
104 if err != nil {
105 return err
106 }
107
108 // Close file on function exit
109 defer srcFile.Close()
110
111 fmt.Fprintf(args.Out, "Creating directory %s\n", srcFileInfo.Name())
112 // Make directory on drive
113 f, err := self.mkdir(MkdirArgs{
114 Out: args.Out,
115 Name: srcFileInfo.Name(),
116 Parents: args.Parents,
117 Description: args.Description,
118 })
119 if err != nil {
120 return err
121 }
122
123 // Read files from directory
124 names, err := srcFile.Readdirnames(0)
125 if err != nil && err != io.EOF {
126 return fmt.Errorf("Failed reading directory: %s", err)
127 }
128
129 for _, name := range names {
130 // Copy args and set new path and parents
131 newArgs := args
132 newArgs.Path = filepath.Join(args.Path, name)
133 newArgs.Parents = []string{f.Id}
134 newArgs.Description = ""
135
136 // Upload
137 err = self.uploadRecursive(newArgs)
138 if err != nil {
139 return err
140 }
141 }
142
143 return nil
144 }
145
146 func (self *Drive) uploadFile(args UploadArgs) (*drive.File, int64, error) {
147 srcFile, srcFileInfo, err := openFile(args.Path)
148 if err != nil {
149 return nil, 0, err
150 }
151
152 // Close file on function exit
153 defer srcFile.Close()
154
155 // Instantiate empty drive file
156 dstFile := &drive.File{Description: args.Description}
157
158 // Use provided file name or use filename
159 if args.Name == "" {
160 dstFile.Name = filepath.Base(srcFileInfo.Name())
161 } else {
162 dstFile.Name = args.Name
163 }
164
165 // Set provided mime type or get type based on file extension
166 if args.Mime == "" {
167 dstFile.MimeType = mime.TypeByExtension(filepath.Ext(dstFile.Name))
168 } else {
169 dstFile.MimeType = args.Mime
170 }
171
172 // Set parent folders
173 dstFile.Parents = args.Parents
174
175 // Chunk size option
176 chunkSize := googleapi.ChunkSize(int(args.ChunkSize))
177
178 // Wrap file in progress reader
179 progressReader := getProgressReader(srcFile, args.Progress, srcFileInfo.Size())
180
181 // Wrap reader in timeout reader
182 reader, ctx := getTimeoutReaderContext(progressReader, args.Timeout)
183
184 fmt.Fprintf(args.Out, "Uploading %s\n", args.Path)
185 started := time.Now()
186
187 f, err := self.service.Files.Create(dstFile).Fields("id", "name", "size", "md5Checksum", "webContentLink").Context(ctx).Media(reader, chunkSize).Do()
188 if err != nil {
189 if isTimeoutError(err) {
190 return nil, 0, fmt.Errorf("Failed to upload file: timeout, no data was transferred for %v", args.Timeout)
191 }
192 return nil, 0, fmt.Errorf("Failed to upload file: %s", err)
193 }
194
195 // Calculate average upload rate
196 rate := calcRate(f.Size, started, time.Now())
197
198 return f, rate, nil
199 }
200
201 type UploadStreamArgs struct {
202 Out io.Writer
203 In io.Reader
204 Name string
205 Description string
206 Parents []string
207 Mime string
208 Share bool
209 ChunkSize int64
210 Progress io.Writer
211 Timeout time.Duration
212 }
213
214 func (self *Drive) UploadStream(args UploadStreamArgs) error {
215 if args.ChunkSize > intMax()-1 {
216 return fmt.Errorf("Chunk size is to big, max chunk size for this computer is %d", intMax()-1)
217 }
218
219 // Instantiate empty drive file
220 dstFile := &drive.File{Name: args.Name, Description: args.Description}
221
222 // Set mime type if provided
223 if args.Mime != "" {
224 dstFile.MimeType = args.Mime
225 }
226
227 // Set parent folders
228 dstFile.Parents = args.Parents
229
230 // Chunk size option
231 chunkSize := googleapi.ChunkSize(int(args.ChunkSize))
232
233 // Wrap file in progress reader
234 progressReader := getProgressReader(args.In, args.Progress, 0)
235
236 // Wrap reader in timeout reader
237 reader, ctx := getTimeoutReaderContext(progressReader, args.Timeout)
238
239 fmt.Fprintf(args.Out, "Uploading %s\n", dstFile.Name)
240 started := time.Now()
241
242 f, err := self.service.Files.Create(dstFile).Fields("id", "name", "size", "webContentLink").Context(ctx).Media(reader, chunkSize).Do()
243 if err != nil {
244 if isTimeoutError(err) {
245 return fmt.Errorf("Failed to upload file: timeout, no data was transferred for %v", args.Timeout)
246 }
247 return fmt.Errorf("Failed to upload file: %s", err)
248 }
249
250 // Calculate average upload rate
251 rate := calcRate(f.Size, started, time.Now())
252
253 fmt.Fprintf(args.Out, "Uploaded %s at %s/s, total %s\n", f.Id, formatSize(rate, false), formatSize(f.Size, false))
254 if args.Share {
255 err = self.shareAnyoneReader(f.Id)
256 if err != nil {
257 return err
258 }
259
260 fmt.Fprintf(args.Out, "File is readable by anyone at %s\n", f.WebContentLink)
261 }
262 return nil
263 }