R语言for循环中download.file遇USGS 401未授权错误的解决问询
解决USGS栅格瓦片下载的401授权问题(Mac + R语言)
问题场景
我在Mac系统下使用R语言,尝试从USGS网站下载一系列GFCC30TC栅格瓦片,原代码如下:
tdir = tempdir() tiles = c("p017r030", "p016r030", "p017r031", "p016r031", "p015r030", "p014r030", "p014r031") for(k in unique(tiles)){ tileurl=paste("https://e4ftl01.cr.usgs.gov/MEASURES/GFCC30TC.003/2015.01.01/GFCC30TC_",k,"_TC_2015.zip",sep="") download.file(tileurl,destfile = file.path(paste(tdir,"Canopy",k,".zip",sep=""))) unzip(file.path(paste(tdir,"Canopy",k,".zip",sep=""),exdir=tdir)) Canopy_tile = paste("Canopy_tile",k,sep="") assign(Canopy_tile,terra::rast(paste(tdir,"Canopy",k,".zip",sep="")))}
但首次访问数据需要USGS登录,运行后出现401未授权错误:
#> Warning in download.file(tileurl, destfile = file.path(paste(tdir, #> "Canopy", : cannot open URL 'https://urs.earthdata.nasa.gov/oauth/authorize? #> scope=uid&app_type=401&client_id=ijpRZvb9qeKCK5ctsn75Tg&response_type=code&redirect_uri=https%3A%2F%2Fe4ftl01.cr.usgs.gov%2Foauth&state=aHR0cHM6Ly9lNGZ0bDAxLmNyLnVzZ3MuZ292L01FQVNVUkVTL0dGQ0MzMFRDLjAwMy8yMDE1LjAxLjAxL0dGQ0MzMFRDX3AwMTdyMDMwX1RDXzIwMTUuemlw': #> HTTP status was '401 Unauthorized' #> Error in download.file(tileurl, destfile = file.path(paste(tdir, "Canopy", : cannot open URL 'https://e4ftl01.cr.usgs.gov/MEASURES/GFCC30TC.003/2015.01.01/GFCC30TC_p017r030_TC_2015.zip'
需要在循环中添加仅首次执行的登录步骤解决该问题。
解决方案
可以通过建立持久化HTTP会话实现仅首次登录,后续循环复用会话状态完成下载。推荐使用httr包处理认证和会话,具体实现如下:
1. 安装并加载必要包
install.packages(c("httr", "terra")) library(httr) library(terra)
2. 初始化会话并完成首次登录(仅执行一次)
创建会话对象,完成登录验证后,后续所有请求复用该会话的认证状态:
# 初始化针对USGS服务器的会话 session <- httr::handle("https://e4ftl01.cr.usgs.gov") # 替换为你的USGS/Earth Data用户名和密码 username <- "你的用户名" password <- "你的密码" # 执行首次登录验证 login_response <- httr::GET( url = "https://e4ftl01.cr.usgs.gov/MEASURES/GFCC30TC.003/2015.01.01/", handle = session, authenticate(username, password, type = "basic") ) # 检查登录状态 if (httr::status_code(login_response) == 200) { message("登录成功,开始下载瓦片...") } else { stop("登录失败,请检查用户名和密码") }
3. 修改循环,复用会话下载文件
调整原循环逻辑,使用已认证的会话下载文件,避免重复登录:
tdir <- tempdir() tiles <- c("p017r030", "p016r030", "p017r031", "p016r031", "p015r030", "p014r030", "p014r031") for(k in unique(tiles)){ tileurl <- paste0("https://e4ftl01.cr.usgs.gov/MEASURES/GFCC30TC.003/2015.01.01/GFCC30TC_", k, "_TC_2015.zip") dest_path <- file.path(tdir, paste0("Canopy", k, ".zip")) # 使用已认证会话下载文件 download_response <- httr::GET( url = tileurl, handle = session, write_disk(dest_path, overwrite = TRUE) ) # 处理下载结果 if (httr::status_code(download_response) == 200) { message(paste("瓦片", k, "下载完成")) unzip(dest_path, exdir = tdir) canopy_tile <- terra::rast(dest_path) assign(paste0("Canopy_tile", k), canopy_tile, envir = .GlobalEnv) } else { warning(paste("瓦片", k, "下载失败,HTTP状态码:", httr::status_code(download_response))) } }
补充说明
- 若不想在代码中明文存储密码,可创建
~/.netrc文件(Mac系统),内容格式如下:machine urs.earthdata.nasa.gov login 你的用户名 password 你的密码httr会自动读取该文件的认证信息,无需在代码中填写用户名密码。 - 会话对象会自动保持登录状态,所有后续下载请求无需重复验证,完全满足仅首次登录的需求。
内容的提问来源于stack exchange,提问作者geoscience123
相关产品推荐
相关产品推荐

