File: drive_download.R

package info (click to toggle)
r-cran-googledrive 2.1.1-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 2,584 kB
  • sloc: sh: 13; makefile: 2
file content (155 lines) | stat: -rw-r--r-- 5,264 bytes parent folder | download | duplicates (2)
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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
#' Download a Drive file
#'
#' @description This function downloads a file from Google Drive. Native Google
#'   file types, such as Google Docs, Google Sheets, and Google Slides, must be
#'   exported to a conventional local file type. This can be specified:

#'   * explicitly via `type`
#'   * implicitly via the file extension of `path`
#'   * not at all, i.e. rely on the built-in default
#'
#' @description To see what export file types are even possible, see the [Drive
#'   API
#'   documentation](https://developers.google.com/drive/api/v3/ref-export-formats)
#'    or the result of `drive_about()$exportFormats`. The returned dribble
#'   includes a `local_path` column.
#'
#' @seealso [Download
#'   files](https://developers.google.com/drive/api/v3/manage-downloads), in the
#'   Drive API documentation.
#'
#' @template file-singular
#' @param path Character. Path for output file. If absent, the default file name
#'   is the file's name on Google Drive and the default location is working
#'   directory, possibly with an added file extension.
#' @param type Character. Only consulted if `file` is a native Google file.
#'   Specifies the desired type of the exported file. Will be processed via
#'   [drive_mime_type()], so either a file extension like `"pdf"` or a full MIME
#'   type like `"application/pdf"` is acceptable.
#' @param overwrite A logical scalar. If local `path` already exists, do you
#'   want to overwrite it?
#' @template verbose
#' @eval return_dribble()
#' @export
#' @examplesIf drive_has_token()
#' # Target one of the official example files
#' (src_file <- drive_example_remote("chicken_sheet"))
#'
#' # Download Sheet as csv, explicit type
#' downloaded_file <- drive_download(src_file, type = "csv")
#'
#' # See local path to new file
#' downloaded_file$local_path
#'
#' # Download as csv, type implicit in file extension
#' drive_download(src_file, path = "my_csv_file.csv")
#'
#' # Download with default name and type (xlsx)
#' drive_download(src_file)
#'
#' # Clean up
#' unlink(c("chicken_sheet.csv", "chicken_sheet.xlsx", "my_csv_file.csv"))
drive_download <- function(file,
                           path = NULL,
                           type = NULL,
                           overwrite = FALSE,
                           verbose = deprecated()) {
  warn_for_verbose(verbose)
  if (!is.null(path) && file.exists(path) && !overwrite) {
    drive_abort(c(
      "Local {.arg path} already exists and overwrite is {.code FALSE}:",
      bulletize(gargle_map_cli(path, "{.path <<x>>}"))
    ))
  }
  file <- as_dribble(file)
  file <- confirm_single_file(file)

  ## preserve extension from path, before possible override by file$name
  ext <- file_ext_safe(path)
  path <- path %||% file$name

  mime_type <- file$drive_resource[[1]]$mimeType

  if (!grepl("google", mime_type) && !is.null(type)) {
    drive_bullets(c(
      "!" = "Ignoring {.arg type}. Only consulted for native Google file types.",
      " " = "MIME type of {.arg file}: {.field mime_type}."
    ))
  }

  if (grepl("google", mime_type)) {
    export_type <- type %||% ext %||% get_export_mime_type(mime_type)
    export_type <- drive_mime_type(export_type)
    verify_export_mime_type(mime_type, export_type)
    path <- apply_extension(path, drive_extension(export_type))

    request <- request_generate(
      endpoint = "drive.files.export",
      params = list(
        fileId = file$id,
        mimeType = export_type
      )
    )
  } else {
    request <- request_generate(
      endpoint = "drive.files.get",
      params = list(
        fileId = file$id,
        alt = "media"
      )
    )
  }

  response <- request_make(
    request,
    httr::write_disk(path, overwrite = overwrite)
  )
  success <- httr::status_code(response) == 200 && file.exists(path)

  if (success) {
    drive_bullets(c(
      "File downloaded:",
      bulletize(gargle_map_cli(file)),
      "Saved locally as:",
      "*" = "{.path {path}}"
    ))
  } else {
    drive_abort("Download failed.")
  }
  invisible(put_column(file, nm = "local_path", val = path, .after = "name"))
}

## get the default export MIME type for a native Google MIME type
## examples:
##    Google Doc --> MS Word
##  Google Sheet --> MS Excel
## Google Slides --> MS PowerPoint
get_export_mime_type <- function(mime_type) {
  m <- .drive$translate_mime_types$mime_type_google == mime_type &
    is_true(.drive$translate_mime_types$default)
  if (!any(m)) {
    drive_abort(c(
      "Not a recognized Google MIME type:",
      bulletize(gargle_map_cli(mime_type), bullet = "x")
    ))
  }
  .drive$translate_mime_types$mime_type_local[m]
}

## affirm that export_type is a valid export MIME type for a native Google file
## of type mime_type
verify_export_mime_type <- function(mime_type, export_type) {
  m <- .drive$translate_mime_types$mime_type_google == mime_type
  ok <- export_type %in% .drive$translate_mime_types$mime_type_local[m]
  if (!ok) {
    ## to be really nice, we would look these up in drive_mime_type() tibble
    ## and use the human_type, if found
    drive_abort(c(
      "Cannot export Google file of type:",
      bulletize(gargle_map_cli(mime_type)),
      "as a file of type:",
      bulletize(gargle_map_cli(export_type))
    ))
  }
  export_type
}