aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drive/download.go91
-rw-r--r--drive/util.go9
-rw-r--r--gdrive.go11
-rw-r--r--handlers_drive.go4
4 files changed, 104 insertions, 11 deletions
diff --git a/drive/download.go b/drive/download.go
index e5674ad..9434ca6 100644
--- a/drive/download.go
+++ b/drive/download.go
@@ -4,25 +4,46 @@ import (
"fmt"
"io"
"os"
+ "time"
+ "path/filepath"
+ "google.golang.org/api/drive/v3"
)
-type DownloadFileArgs struct {
+type DownloadArgs struct {
Out io.Writer
Progress io.Writer
Id string
+ Path string
Force bool
+ Recursive bool
Stdout bool
}
-func (self *Drive) Download(args DownloadFileArgs) (err error) {
- getFile := self.service.Files.Get(args.Id)
+func (self *Drive) Download(args DownloadArgs) error {
+ return self.download(args)
+}
- f, err := getFile.Do()
+func (self *Drive) download(args DownloadArgs) error {
+ f, err := self.service.Files.Get(args.Id).Fields("id", "name", "size", "mimeType", "md5Checksum").Do()
if err != nil {
return fmt.Errorf("Failed to get file: %s", err)
}
- res, err := getFile.Download()
+ if isDir(f) && !args.Recursive {
+ return fmt.Errorf("'%s' is a directory, use --recursive to download directories", f.Name)
+ } else if isDir(f) && args.Recursive {
+ return self.downloadDirectory(f, args)
+ } else if isBinary(f) {
+ return self.downloadBinary(f, args)
+ } else if !args.Recursive {
+ return fmt.Errorf("'%s' is a google document and must be exported, see the export command", f.Name)
+ }
+
+ return nil
+}
+
+func (self *Drive) downloadBinary(f *drive.File, args DownloadArgs) error {
+ res, err := self.service.Files.Get(f.Id).Download()
if err != nil {
return fmt.Errorf("Failed to download file: %s", err)
}
@@ -39,13 +60,20 @@ func (self *Drive) Download(args DownloadFileArgs) (err error) {
return err
}
+ filename := filepath.Join(args.Path, f.Name)
+
// Check if file exists
- if !args.Force && fileExists(f.Name) {
- return fmt.Errorf("File '%s' already exists, use --force to overwrite", f.Name)
+ if !args.Force && fileExists(filename) {
+ return fmt.Errorf("File '%s' already exists, use --force to overwrite", filename)
+ }
+
+ // Ensure any parent directories exists
+ if err = mkdir(filename); err != nil {
+ return err
}
// Create new file
- outFile, err := os.Create(f.Name)
+ outFile, err := os.Create(filename)
if err != nil {
return fmt.Errorf("Unable to create new file: %s", err)
}
@@ -53,16 +81,59 @@ func (self *Drive) Download(args DownloadFileArgs) (err error) {
// Close file on function exit
defer outFile.Close()
+ fmt.Fprintf(args.Out, "\nDownloading %s...\n", f.Name)
+ started := time.Now()
+
// Save file to disk
bytes, err := io.Copy(outFile, srcReader)
if err != nil {
return fmt.Errorf("Failed saving file: %s", err)
}
- fmt.Fprintf(args.Out, "Downloaded '%s' at %s, total %d\n", f.Name, "x/s", bytes)
+ // Calculate average download rate
+ rate := calcRate(f.Size, started, time.Now())
+
+ fmt.Fprintf(args.Out, "Downloaded '%s' at %s/s, total %s\n", filename, formatSize(rate, false), formatSize(bytes, false))
//if deleteSourceFile {
// self.Delete(args.Id)
//}
- return
+ return nil
+}
+
+func (self *Drive) downloadDirectory(parent *drive.File, args DownloadArgs) error {
+ query := fmt.Sprintf("'%s' in parents", parent.Id)
+ fileList, err := self.service.Files.List().Q(query).Fields("files(id,name)").Do()
+ if err != nil {
+ return fmt.Errorf("Failed listing files: %s", err)
+ }
+
+ // Update download path
+ path := filepath.Join(args.Path, parent.Name)
+
+ for _, f := range fileList.Files {
+ err = self.download(DownloadArgs{
+ Out: args.Out,
+ Id: f.Id,
+ Progress: args.Progress,
+ Force: args.Force,
+ Path: path,
+ Recursive: args.Recursive,
+ Stdout: false,
+ })
+
+ if err != nil {
+ return err
+ }
+ }
+
+ return nil
+}
+
+func isDir(f *drive.File) bool {
+ return f.MimeType == DirectoryMimeType
+}
+
+func isBinary(f *drive.File) bool {
+ return f.Md5Checksum != ""
}
diff --git a/drive/util.go b/drive/util.go
index 8b3d171..f492286 100644
--- a/drive/util.go
+++ b/drive/util.go
@@ -3,6 +3,7 @@ package drive
import (
"os"
"fmt"
+ "path/filepath"
"strings"
"strconv"
"unicode/utf8"
@@ -122,6 +123,14 @@ func fileExists(path string) bool {
return false
}
+func mkdir(path string) error {
+ dir := filepath.Dir(path)
+ if fileExists(dir) {
+ return nil
+ }
+ return os.MkdirAll(dir, 0775)
+}
+
func intMax() int64 {
return 1 << (strconv.IntSize - 1) - 1
}
diff --git a/gdrive.go b/gdrive.go
index 8698911..71e4a7b 100644
--- a/gdrive.go
+++ b/gdrive.go
@@ -110,6 +110,17 @@ func main() {
Description: "Overwrite existing file",
OmitValue: true,
},
+ cli.StringFlag{
+ Name: "path",
+ Patterns: []string{"--path"},
+ Description: "Download path",
+ },
+ cli.BoolFlag{
+ Name: "recursive",
+ Patterns: []string{"-r", "--recursive"},
+ Description: "Download directory recursively, documents will be skipped",
+ OmitValue: true,
+ },
cli.BoolFlag{
Name: "noProgress",
Patterns: []string{"--no-progress"},
diff --git a/handlers_drive.go b/handlers_drive.go
index 04075f4..38c1e1c 100644
--- a/handlers_drive.go
+++ b/handlers_drive.go
@@ -30,10 +30,12 @@ func listHandler(ctx cli.Context) {
func downloadHandler(ctx cli.Context) {
args := ctx.Args()
- err := newDrive(args).Download(drive.DownloadFileArgs{
+ err := newDrive(args).Download(drive.DownloadArgs{
Out: os.Stdout,
Id: args.String("id"),
Force: args.Bool("force"),
+ Path: args.String("path"),
+ Recursive: args.Bool("recursive"),
Stdout: args.Bool("stdout"),
Progress: progressWriter(args.Bool("noProgress")),
})