什么是R的download.file的“内部方法”?

时间:2015-06-18 04:22:20

标签: r download

我正在尝试使用download.file下载以下数据集,该数据集只适用于method = "wget"

# Doesn't work
download.file('http://uofi.box.com/shared/static/bba3968d7c3397c024ec.dta', tempfile(), method = "auto")
download.file('http://uofi.box.com/shared/static/bba3968d7c3397c024ec.dta', tempfile(), method = "curl")

# Works
download.file('http://uofi.box.com/shared/static/bba3968d7c3397c024ec.dta', tempfile(), method = "wget")

根据help(download.file)

  

如果选择method =“auto”(默认值),则内部方法为   为file:// URL和其他提供的URL选择   功能(“http / ftp”)是真的(几乎总是如此)。

查看源代码,“内部方法”是指:

if (method == "internal") {
        status <- .External(C_download, url, destfile, quiet, 
            mode, cacheOK)
        if (!quiet) 
            flush.console()
    }

但是,我仍然不知道.External(C_download)做了什么,特别是跨平台。对我来说,了解这一点并不依赖于wget非常重要,因为我正在撰写一个应该跨平台工作的软件包。

2 个答案:

答案 0 :(得分:3)

此源代码位于R源代码中(从http://cran.r-project.org/sources.html下载当前版本)。相关代码(自R 3.2.1起)位于&#34; ./ src / modules / internet / internet.c&#34;和&#34; ./ src / modules / internet / nanohttp.c&#34;。

根据后者,极简主义HTTP GET功能的代码基于libxml2-2.3.6。

如果您不想下载整个.tgz文件并将其解压缩,则可以在R {s}网站https://svn.r-project.org/R/branches/R-3-2-branch/src/modules/internet/internet.chttps://svn.r-project.org/R/branches/R-3-2-branch/src/modules/internet/nanohttp.c上找到这些文件。

如果查看代码,大多数代码在不同平台上都是一致的。但是,在Windows上,似乎使用了wininet代码。

最初在utils包中查找代码,因为这是找到R命令download.file的地方。我grep可以在&#34; ./ src / library / utils / src&#34;中的c文件中下载。目录,发现相关代码在&#34; sock.c&#34;。该文件中有一条评论高达/* from src/main/internet.c */所以我接下来去了#34; internet.c&#34;。

对于您的特定文件,问题是您所拥有的链接会返回302 Found状态代码。在Windows上并使用wget,下载例程遵循302响应的Location字段并获取实际文件。使用curl方法有效但仅当您提供参数extra="-L"

download.file('http://uofi.box.com/shared/static/bba3968d7c3397c024ec.dta', tempfile(), method = "curl", extra="-L")

有一个名为downloader的软件包声称可以为https提供良好的跨平台解决方案。给定一个http URL,它只是将调用传递给download.file。这是一个适用于http的版本。它也默认为二进制传输,这似乎是一个好主意。

my_download <- function(url, destfile, method, quiet = FALSE,
                        mode = "wb", cacheOK = TRUE, extra = getOption("download.file.extra")) {
  if (.Platform$OS.type == "windows" && (missing(method) || method %in% c("auto", "internal", "wininet"))) {
    seti2 <- utils::"setInternet2"
    internet2_start <- seti2(NA)
    on.exit(suppressWarnings(seti2(internet2_start)))
    suppressWarnings(seti2(TRUE))
  } else {
    if (missing(method)) {
      if (nzchar(Sys.which("wget")[1])) {
        method <- "wget"
      } else if (nzchar(Sys.which("curl")[1])) {
        method <- "curl"
        if (!grepl("-L", extra)) {
          extra <- paste("-L", extra)
        }
      } else if (nzchar(Sys.which("lynx")[1])) {
        method <- "lynx"
      } else {
        stop("no download method found")
      }
    }
  }
  download.file(url = url, destfile = destfile, method = method, quiet = quiet, mode = mode,
                cacheOK = cacheOK, extra = extra)
}

答案 1 :(得分:0)

你可以自己回答这个问题。只需在控制台提示符下键入download.file,您就会在函数定义的顶部看到它:

if (method == "auto") {   # this is actually the default from
                          # getOption("download.file.method", default = "auto")

        if (capabilities("http/ftp")) 
            method <- "internal"
        else if (length(grep("^file:", url))) {
            method <- "internal"
            url <- URLdecode(url)
        }
        else if (system("wget --help > /dev/null") == 0L) 
            method <- "wget"
        else if (system("curl --help > /dev/null") == 0L) 
            method <- "curl"
        else if (system("lynx -help > /dev/null") == 0L) 
            method <- "lynx"
        else stop("no download method found")
    }
    if (method == "internal") {
        status <- .External(C_download, url, destfile, quiet, 
            mode, cacheOK)
        if (!quiet) 
            flush.console()
    }