File: req-progress.R

package info (click to toggle)
r-cran-httr2 1.2.2-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 1,684 kB
  • sloc: sh: 13; makefile: 2
file content (72 lines) | stat: -rw-r--r-- 1,738 bytes parent folder | download
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
#' Add a progress bar to long downloads or uploads
#'
#' When uploading or downloading a large file, it's often useful to
#' provide a progress bar so that you know how long you have to wait.
#'
#' @inheritParams req_headers
#' @param type Type of progress to display: either number of bytes uploaded
#'   or downloaded.
#' @export
#' @examples
#' req <- request("https://r4ds.s3.us-west-2.amazonaws.com/seattle-library-checkouts.csv") |>
#'   req_progress()
#'
#' \dontrun{
#' path <- tempfile()
#' req |> req_perform(path = path)
#' }
req_progress <- function(req, type = c("down", "up")) {
  type <- arg_match(type)

  # https://curl.se/libcurl/c/CURLOPT_XFERINFOFUNCTION.html
  req_options(req, noprogress = FALSE, xferinfofunction = make_progress(type))
}

make_progress <- function(type, frame = caller_env()) {
  force(type)
  init <- FALSE

  function(down, up) {
    if (type == "down") {
      total <- down[[1]]
      now <- down[[2]]
      verb <- "Downloading"
    } else {
      total <- up[[1]]
      now <- up[[2]]
      verb <- "Uploading"
    }

    if (total == 0 && now == 0) {
      init <<- FALSE
      return(TRUE)
    }

    if (!init) {
      init <<- TRUE
      if (total == 0) {
        cli::cli_progress_bar(
          format = paste0(verb, " {cli::pb_spin}"),
          .envir = frame
        )
      } else {
        cli::cli_progress_bar(
          format = paste0(
            verb,
            " {cli::pb_percent} {cli::pb_bar} {cli::pb_eta}"
          ),
          total = total,
          .envir = frame
        )
      }
    }

    if (now < total && total > 0) {
      cli::cli_progress_update(set = now, .envir = frame)
    } else {
      cli::cli_progress_done(.envir = frame)
    }

    TRUE
  }
}