func (self *Drive) Update(args UpdateArgs) error { srcFile, srcFileInfo, err := openFile(args.Path) if err != nil { return fmt.Errorf("Failed to open file: %s", err) } defer srcFile.Close() // Instantiate empty drive file dstFile := &drive.File{Description: args.Description} // Use provided file name or use filename if args.Name == "" { dstFile.Name = filepath.Base(srcFileInfo.Name()) } else { dstFile.Name = args.Name } // Set provided mime type or get type based on file extension if args.Mime == "" { dstFile.MimeType = mime.TypeByExtension(filepath.Ext(dstFile.Name)) } else { dstFile.MimeType = args.Mime } // Set parent folders dstFile.Parents = args.Parents // Chunk size option chunkSize := googleapi.ChunkSize(int(args.ChunkSize)) // Wrap file in progress reader progressReader := getProgressReader(srcFile, args.Progress, srcFileInfo.Size()) // Wrap reader in timeout reader reader, ctx := getTimeoutReaderContext(progressReader, args.Timeout) fmt.Fprintf(args.Out, "Uploading %s\n", args.Path) started := time.Now() f, err := self.service.Files.Update(args.Id, dstFile).Fields("id", "name", "size").Context(ctx).Media(reader, chunkSize).Do() if err != nil { if isTimeoutError(err) { return fmt.Errorf("Failed to upload file: timeout, no data was transferred for %v", args.Timeout) } return fmt.Errorf("Failed to upload file: %s", err) } // Calculate average upload rate rate := calcRate(f.Size, started, time.Now()) fmt.Fprintf(args.Out, "Updated %s at %s/s, total %s\n", f.Id, formatSize(rate, false), formatSize(f.Size, false)) return nil }
func (self *Drive) UploadStream(args UploadStreamArgs) error { if args.ChunkSize > intMax()-1 { return fmt.Errorf("Chunk size is to big, max chunk size for this computer is %d", intMax()-1) } // Instantiate empty drive file dstFile := &drive.File{Name: args.Name} // Set mime type if provided if args.Mime != "" { dstFile.MimeType = args.Mime } // Set parent folders dstFile.Parents = args.Parents // Chunk size option chunkSize := googleapi.ChunkSize(int(args.ChunkSize)) // Wrap file in progress reader progressReader := getProgressReader(args.In, args.Progress, 0) // Wrap reader in timeout reader reader, ctx := getTimeoutReaderContext(progressReader, args.Timeout) fmt.Fprintf(args.Out, "Uploading %s\n", dstFile.Name) started := time.Now() f, err := self.service.Files.Create(dstFile).Fields("id", "name", "size", "webContentLink").Context(ctx).Media(reader, chunkSize).Do() if err != nil { if isTimeoutError(err) { return fmt.Errorf("Failed to upload file: timeout, no data was transferred for %v", args.Timeout) } return fmt.Errorf("Failed to upload file: %s", err) } // Calculate average upload rate rate := calcRate(f.Size, started, time.Now()) fmt.Fprintf(args.Out, "Uploaded %s at %s/s, total %s\n", f.Id, formatSize(rate, false), formatSize(f.Size, false)) if args.Share { err = self.shareAnyoneReader(f.Id) if err != nil { return err } fmt.Fprintf(args.Out, "File is readable by anyone at %s\n", f.WebContentLink) } return nil }
func (w *Writer) open() error { attrs := w.ObjectAttrs // Check the developer didn't change the object Name (this is unfortunate, but // we don't want to store an object under the wrong name). if attrs.Name != w.o.object { return fmt.Errorf("storage: Writer.Name %q does not match object name %q", attrs.Name, w.o.object) } if !utf8.ValidString(attrs.Name) { return fmt.Errorf("storage: object name %q is not valid UTF-8", attrs.Name) } pr, pw := io.Pipe() w.pw = pw w.opened = true if w.ChunkSize < 0 { return errors.New("storage: Writer.ChunkSize must non-negative") } mediaOpts := []googleapi.MediaOption{ googleapi.ChunkSize(w.ChunkSize), } if c := attrs.ContentType; c != "" { mediaOpts = append(mediaOpts, googleapi.ContentType(c)) } go func() { defer close(w.donec) call := w.o.c.raw.Objects.Insert(w.o.bucket, attrs.toRawObject(w.o.bucket)). Media(pr, mediaOpts...). Projection("full"). Context(w.ctx) if err := setEncryptionHeaders(call.Header(), w.o.encryptionKey, false); err != nil { w.err = err pr.CloseWithError(w.err) return } var resp *raw.Object err := applyConds("NewWriter", w.o.gen, w.o.conds, call) if err == nil { err = runWithRetry(w.ctx, func() error { resp, err = call.Do(); return err }) } if err != nil { w.err = err pr.CloseWithError(w.err) return } w.obj = newObject(resp) }() return nil }
func (self *Drive) uploadMissingFile(parentId string, lf *LocalFile, args UploadSyncArgs, try int) error { if args.DryRun { return nil } srcFile, err := os.Open(lf.absPath) if err != nil { return fmt.Errorf("Failed to open file: %s", err) } // Close file on function exit defer srcFile.Close() // Instantiate drive file dstFile := &drive.File{ Name: lf.info.Name(), Parents: []string{parentId}, AppProperties: map[string]string{"sync": "true", "syncRootId": args.RootId}, } // Chunk size option chunkSize := googleapi.ChunkSize(int(args.ChunkSize)) // Wrap file in progress reader progressReader := getProgressReader(srcFile, args.Progress, lf.info.Size()) // Wrap reader in timeout reader reader, ctx := getTimeoutReaderContext(progressReader, args.Timeout) _, err = self.service.Files.Create(dstFile).Fields("id", "name", "size", "md5Checksum").Context(ctx).Media(reader, chunkSize).Do() if err != nil { if isBackendOrRateLimitError(err) && try < MaxErrorRetries { exponentialBackoffSleep(try) try++ return self.uploadMissingFile(parentId, lf, args, try) } else if isTimeoutError(err) { return fmt.Errorf("Failed to upload file: timeout, no data was transferred for %v", args.Timeout) } else { return fmt.Errorf("Failed to upload file: %s", err) } } return nil }
func (self *Drive) updateChangedFile(cf *changedFile, args UploadSyncArgs, try int) error { if args.DryRun { return nil } srcFile, err := os.Open(cf.local.absPath) if err != nil { return fmt.Errorf("Failed to open file: %s", err) } // Close file on function exit defer srcFile.Close() // Instantiate drive file dstFile := &drive.File{} // Chunk size option chunkSize := googleapi.ChunkSize(int(args.ChunkSize)) // Wrap file in progress reader progressReader := getProgressReader(srcFile, args.Progress, cf.local.info.Size()) // Wrap reader in timeout reader reader, ctx := getTimeoutReaderContext(progressReader, args.Timeout) _, err = self.service.Files.Update(cf.remote.file.Id, dstFile).Context(ctx).Media(reader, chunkSize).Do() if err != nil { if isBackendOrRateLimitError(err) && try < MaxErrorRetries { exponentialBackoffSleep(try) try++ return self.updateChangedFile(cf, args, try) } else if isTimeoutError(err) { return fmt.Errorf("Failed to upload file: timeout, no data was transferred for %v", args.Timeout) } else { return fmt.Errorf("Failed to update file: %s", err) } } return nil }
func (gd *GDrive) UploadFile(fname string, r io.Reader) error { srv, err := drive.New(gd.client) if err != nil { logError.Printf("Unable to retrieve drive Client %v", err) return err } mo := googleapi.ChunkSize(googleapi.DefaultUploadChunkSize) fc := srv.Files.Create(&drive.File{Name: fname}) fc = fc.Media(r, mo) logInfo.Printf("%v", fc) f, err := fc.Do() if err != nil { logError.Printf("Unable to upload file: %v.", err) return err } logInfo.Printf("%s (%s)\n", f.Name, f.Id) return nil }