#' Update an existing Drive file
#'
#' Update an existing Drive file id with new content ("media" in Drive
#' API-speak), new metadata, or both. To create a new file or update existing,
#' depending on whether the Drive file already exists, see [drive_put()].
#'
#' @seealso Wraps the `files.update` endpoint:
#' * <https://developers.google.com/drive/api/v3/reference/files/update>
#'
#' This function supports media upload:
#' * <https://developers.google.com/drive/api/v3/manage-uploads>
#'
#' @template file-singular
#' @template media
#' @template dots-metadata
#' @template verbose
#'
#' @eval return_dribble()
#' @export
#'
#' @examplesIf drive_has_token()
#' # Create a new file, so we can update it
#' x <- drive_example_remote("chicken.csv") %>%
#' drive_cp()
#'
#' # Update the file with new media
#' x <- x %>%
#' drive_update(drive_example_local("chicken.txt"))
#'
#' # Update the file with new metadata.
#' # Notice here `name` is not an argument of `drive_update()`, we are passing
#' # this to the API via the `...``
#' x <- x %>%
#' drive_update(name = "CHICKENS!")
#'
#' # Update the file with new media AND new metadata
#' x <- x %>%
#' drive_update(
#' drive_example_local("chicken.txt"),
#' name = "chicken-poem-again.txt"
#' )
#'
#' # Clean up
#' drive_rm(x)
drive_update <- function(file,
media = NULL,
...,
verbose = deprecated()) {
warn_for_verbose(verbose)
if ((!is.null(media)) && (!file.exists(media))) {
drive_abort(c(
"No file exists at the local {.arg media} path:",
bulletize(gargle_map_cli(media, "{.path <<x>>}"), bullet = "x")
))
}
file <- as_dribble(file)
file <- confirm_single_file(file)
meta <- toCamel(list2(...))
if (is.null(media) && length(meta) == 0) {
drive_bullets(c(
"!" = "No updates specified."
))
return(invisible(file))
}
meta[["fields"]] <- meta[["fields"]] %||% "*"
if (is.null(media)) {
out <- drive_update_metadata(file, meta)
} else {
if (length(meta) == 0) {
out <- drive_update_media(file, media)
} else {
media <- enc2utf8(media)
out <- drive_update_multipart(file, media, meta)
}
}
drive_bullets(c("File updated:", bulletize(gargle_map_cli(out))))
invisible(out)
}
## currently this can never be called, because we always send fields
drive_update_media <- function(file, media) {
request <- request_generate(
endpoint = "drive.files.update.media",
params = list(
fileId = file$id,
uploadType = "media",
fields = "*"
)
)
## media uploads have unique body situations, so customizing here.
request$body <- httr::upload_file(path = media)
response <- request_make(request)
as_dribble(list(gargle::response_process(response)))
}
drive_update_metadata <- function(file, meta) {
params <- meta %||% list()
params$fileId <- file$id
request <- request_generate(
endpoint = "drive.files.update",
params = params
)
response <- request_make(request)
as_dribble(list(gargle::response_process(response)))
}
drive_update_multipart <- function(file, media, meta) {
# We include the metadata here even though it's overwritten below,
# so that request_generate() still validates it.
params <- meta %||% list()
params$fileId <- file$id
params$uploadType <- "multipart"
request <- request_generate(
endpoint = "drive.files.update.media",
params = params
)
meta_file <- withr::local_file(
tempfile("drive-update-meta", fileext = ".json")
)
write_utf8(jsonlite::toJSON(meta), meta_file)
## media uploads have unique body situations, so customizing here.
request$body <- list(
metadata = httr::upload_file(
path = meta_file,
type = "application/json; charset=UTF-8"
),
media = httr::upload_file(path = media)
)
response <- request_make(request, encode = "multipart")
as_dribble(list(gargle::response_process(response)))
}
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.