diff options
| -rw-r--r-- | drive/export.go | 111 | ||||
| -rw-r--r-- | gdrive.go | 27 | ||||
| -rw-r--r-- | handlers.go | 12 | 
3 files changed, 150 insertions, 0 deletions
| diff --git a/drive/export.go b/drive/export.go new file mode 100644 index 0000000..2cbc265 --- /dev/null +++ b/drive/export.go @@ -0,0 +1,111 @@ +package drive + +import ( +    "io" +    "os" +    "fmt" +    "mime" +) + +var DefaultExportMime = map[string]string{ +    "application/vnd.google-apps.form": "application/zip", +    "application/vnd.google-apps.document": "application/pdf", +    "application/vnd.google-apps.drawing": "image/svg+xml", +    "application/vnd.google-apps.spreadsheet": "text/csv", +    "application/vnd.google-apps.script": "application/vnd.google-apps.script+json", +    "application/vnd.google-apps.presentation": "application/pdf", +} + +type ExportArgs struct { +    Out io.Writer +    Id string +    PrintMimes bool +    Mime string +    Force bool +} + +func (self *Drive) Export(args ExportArgs) (err error) { +    f, err := self.service.Files.Get(args.Id).Fields("name", "mimeType").Do() +    if err != nil { +        return fmt.Errorf("Failed to get file: %s", err) +    } + +    if args.PrintMimes { +        return self.printMimes(args.Out, f.MimeType) +    } + +    exportMime, err := getExportMime(args.Mime, f.MimeType) +    if err != nil { +        return err +    } + +    filename := getExportFilename(f.Name, exportMime) + +    res, err := self.service.Files.Export(args.Id, exportMime).Download() +    if err != nil { +        return fmt.Errorf("Failed to download file: %s", err) +    } + +    // Close body on function exit +    defer res.Body.Close() + +    // Check if file exists +    if !args.Force && fileExists(filename) { +        return fmt.Errorf("File '%s' already exists, use --force to overwrite", filename) +    } + +    // Create new file +    outFile, err := os.Create(filename) +    if err != nil { +        return fmt.Errorf("Unable to create new file '%s': %s", filename, err) +    } + +    // Close file on function exit +    defer outFile.Close() + +    // Save file to disk +    bytes, err := io.Copy(outFile, res.Body) +    if err != nil { +        return fmt.Errorf("Failed saving file: %s", err) +    } + +    fmt.Fprintf(args.Out, "Exported '%s' at %s, total %d\n", filename, "x/s", bytes) +    return +} + +func (self *Drive) printMimes(out io.Writer, mimeType string) error { +    about, err := self.service.About.Get().Fields("exportFormats").Do() +    if err != nil { +        return fmt.Errorf("Failed to get about: %s", err) +    } + +    mimes, ok := about.ExportFormats[mimeType] +    if !ok { +        return fmt.Errorf("File with type '%s' cannot be exported", mimeType) +    } + +    fmt.Fprintf(out, "Available mime types: %s\n", formatList(mimes)) +    return nil +} + +func getExportMime(userMime, fileMime string) (string, error) { +    if userMime != "" { +        return userMime, nil +    } + +    defaultMime, ok := DefaultExportMime[fileMime] +    if !ok { +        return "", fmt.Errorf("File with type '%s' does not have a default export mime, and can probably not be exported", fileMime) +    } + +    return defaultMime, nil +} + +func getExportFilename(name, mimeType string) string { +    extensions, err := mime.ExtensionsByType(mimeType) +    if err != nil { +        return name +    } + +    return name + extensions[0] +} @@ -162,6 +162,33 @@ func main() {              },          },          &cli.Handler{ +            Pattern: "[global options] export [options] <id>", +            Description: "Export a google document", +            Callback: exportHandler, +            Flags: cli.Flags{ +                "global options": globalFlags, +                "options": []cli.Flag{ +                    cli.BoolFlag{ +                        Name: "force", +                        Patterns: []string{"-f", "--force"}, +                        Description: "Overwrite existing file", +                        OmitValue: true, +                    }, +                    cli.StringFlag{ +                        Name: "mime", +                        Patterns: []string{"--mime"}, +                        Description: "Mime type of exported file", +                    }, +                    cli.BoolFlag{ +                        Name: "printMimes", +                        Patterns: []string{"--print-mimes"}, +                        Description: "Print available mime types for given file", +                        OmitValue: true, +                    }, +                }, +            }, +        }, +        &cli.Handler{              Pattern: "[global options] mkdir [options] <name>",              Description: "Create directory",              Callback: mkdirHandler, diff --git a/handlers.go b/handlers.go index 5358c9b..31a1887 100644 --- a/handlers.go +++ b/handlers.go @@ -64,6 +64,18 @@ func infoHandler(ctx cli.Context) {      checkErr(err)  } +func exportHandler(ctx cli.Context) { +    args := ctx.Args() +    err := newDrive(args).Export(drive.ExportArgs{ +        Out: os.Stdout, +        Id: args.String("id"), +        Mime: args.String("mime"), +        PrintMimes: args.Bool("printMimes"), +        Force: args.Bool("force"), +    }) +    checkErr(err) +} +  func mkdirHandler(ctx cli.Context) {      args := ctx.Args()      err := newDrive(args).Mkdir(drive.MkdirArgs{ | 
