You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在R中实现仅当服务器文件更新时才下载(类curl -z/-R)

解决方案:在R中实现增量文件下载(适配targets流水线)

方法1:用curl包正确配置libcurl参数

你提到的CURLOPT_TIMECOND_IFMODSINCE对应curl包中的timecondition = 1,但还需要配合timevalue参数传入本地文件的修改时间,同时开启filetime来同步服务器文件的修改时间(对应Shell的-R参数)。

完整实现代码如下:

library(curl)

# 定义目标文件路径
url <- "https://files.digital.nhs.uk/9B/DF836C/hosp-epis-stat-admi-hosp-prov-2022-23-tab_v2.xlsx"
dest_file <- basename(url)

# 创建curl handle并配置参数
h <- curl::new_handle()

# 检查本地文件是否存在,获取修改时间
if (file.exists(dest_file)) {
  # 获取本地文件修改时间(转换为Unix时间戳)
  local_mtime <- file.info(dest_file)$mtime
  curl::handle_setopt(h, timevalue = as.numeric(local_mtime))
}

# 设置时间条件为仅当文件更新时下载(IFMODSINCE)
curl::handle_setopt(h, timecondition = 1)
# 开启获取服务器文件修改时间,用于同步本地文件时间
curl::handle_setopt(h, filetime = 1)

# 执行下载
response <- curl::multi_download(
  urls = url,
  destfile = dest_file,
  handle = h
)

# 同步本地文件修改时间为服务器时间(对应-R参数)
if (!is.null(response$filetime)) {
  Sys.setFileTime(dest_file, as.POSIXct(response$filetime, origin = "1970-01-01"))
}

关键参数说明:

  • timecondition = 1:对应CURLOPT_TIMECOND_IFMODSINCE,仅当服务器文件修改时间晚于timevalue指定的时间时才下载。
  • timevalue:传入本地文件的Unix时间戳,作为判断基准。
  • filetime = 1:让curl返回服务器文件的修改时间,之后用Sys.setFileTime同步到本地文件,实现和-R相同的效果。

方法2:直接调用系统curl命令(简单高效)

如果觉得curl包的参数配置太繁琐,可以直接在R中调用你已经验证过的Shell命令,这在targets流水线中同样适用:

library(processx)

url <- "https://files.digital.nhs.uk/9B/DF836C/hosp-epis-stat-admi-hosp-prov-2022-23-tab_v2.xlsx"
dest_file <- basename(url)

# 调用系统curl命令,实现增量下载+同步修改时间
processx::run(
  command = "curl",
  args = c("-R", "-z", dest_file, url, "-o", dest_file)
)

这种方法完全复用你已经测试过的Shell逻辑,不需要额外学习R curl包的参数,适合快速集成到targets流水线中。

在targets中集成的注意事项

在targets流水线中,你可以将上述代码封装成一个函数,然后定义一个文件目标。targets会根据文件的修改时间自动判断是否需要重新运行该步骤,配合增量下载逻辑能最大限度缩短流水线耗时:

# _targets.R中的示例
library(targets)

tar_option_set(packages = c("curl"))

download_data <- function() {
  url <- "https://files.digital.nhs.uk/9B/DF836C/hosp-epis-stat-admi-hosp-prov-2022-23-tab_v2.xlsx"
  dest_file <- "data/hosp_data.xlsx"
  dir.create("data", showWarnings = FALSE)
  
  # 方法1的curl包实现代码
  h <- curl::new_handle()
  if (file.exists(dest_file)) {
    local_mtime <- file.info(dest_file)$mtime
    curl::handle_setopt(h, timevalue = as.numeric(local_mtime))
  }
  curl::handle_setopt(h, timecondition = 1, filetime = 1)
  response <- curl::multi_download(url, dest_file, handle = h)
  if (!is.null(response$filetime)) {
    Sys.setFileTime(dest_file, as.POSIXct(response$filetime, origin = "1970-01-01"))
  }
  dest_file
}

list(
  tar_target(
    name = raw_data_file,
    command = download_data(),
    format = "file" # 告诉targets这是一个文件目标,基于文件修改时间判断是否更新
  )
)

内容的提问来源于stack exchange,提问作者Ollie

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 00:42:51