aboutsummaryrefslogtreecommitdiffstats
path: root/drive/revision_download.go
blob: 6bed8862782a6bb0b1a4a19233e8b6a12ecc4242 (plain)
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
package drive

import (
	"fmt"
	"io"
	"io/ioutil"
	"path/filepath"
	"time"
)

type DownloadRevisionArgs struct {
	Out        io.Writer
	Progress   io.Writer
	FileId     string
	RevisionId string
	Path       string
	Force      bool
	Stdout     bool
	Timeout    time.Duration
}

func (self *Drive) DownloadRevision(args DownloadRevisionArgs) (err error) {
	getRev := self.service.Revisions.Get(args.FileId, args.RevisionId)

	rev, err := getRev.Fields("originalFilename").Do()
	if err != nil {
		return fmt.Errorf("Failed to get file: %s", err)
	}

	if rev.OriginalFilename == "" {
		return fmt.Errorf("Download is not supported for this file type")
	}

	// Get timeout reader wrapper and context
	timeoutReaderWrapper, ctx := getTimeoutReaderWrapperContext(args.Timeout)

	res, err := getRev.Context(ctx).Download()
	if err != nil {
		if isTimeoutError(err) {
			return fmt.Errorf("Failed to download file: timeout, no data was transferred for %v", args.Timeout)
		}
		return fmt.Errorf("Failed to download file: %s", err)
	}

	// Close body on function exit
	defer res.Body.Close()

	// Discard other output if file is written to stdout
	out := args.Out
	if args.Stdout {
		out = ioutil.Discard
	}

	// Path to file
	fpath := filepath.Join(args.Path, rev.OriginalFilename)

	fmt.Fprintf(out, "Downloading %s -> %s\n", rev.OriginalFilename, fpath)

	bytes, rate, err := self.saveFile(saveFileArgs{
		out:           args.Out,
		body:          timeoutReaderWrapper(res.Body),
		contentLength: res.ContentLength,
		fpath:         fpath,
		force:         args.Force,
		stdout:        args.Stdout,
		progress:      args.Progress,
	})

	if err != nil {
		return err
	}

	fmt.Fprintf(out, "Download complete, rate: %s/s, total size: %s\n", formatSize(rate, false), formatSize(bytes, false))
	return nil
}