如何创建签名的S3 URL

4

我想使用data.table包中的fread函数从S3读取CSV文件,代码如下:

 ulr_with_signature <- signURL(url, access_key, secret_key)
 DT <- fread(ulr_with_signature)

有没有可以让我使用访问/秘钥对构建URL的包或代码。

我不想使用awscli来读取数据。


这是一个关于如何直接将数据写入S3并在读取到内存中的问题,以下是答案链接:https://dev59.com/MF0a5IYBdhLWcg3wqKKq - Bulat
2个回答

8
您可以使用AWS S3包
执行读取操作的步骤如下:
# These variables should be set in your environment, but you could set them in R:
Sys.setenv("AWS_ACCESS_KEY_ID" = "mykey",
       "AWS_SECRET_ACCESS_KEY" = "mysecretkey",
       "AWS_DEFAULT_REGION" = "us-east-1")

library("aws.s3")

如果您有一个名为obj的R对象,想要保存到AWS上并稍后读取:
s3save(obj, bucket = "my_bucket", object = "object")
# and then later
obj <- s3load("object", bucket = "my_bucket")

显然,将存储桶名称和文件名(AWS存储桶中对象的名称)替换为实际值。该包还有一个相应的s3save函数。您也可以使用s3saveRDSs3readRDS以RDS格式保存和加载。

如果您需要读取文本文件,则稍微复杂一些,因为库的函数“get_object”返回一个原始向量,我们必须自己解析它:

raw_data <- get_object('data.csv', 'my_bucket')

# this method to parse the data is copied from the httr library
# substitute encoding from as needed
data <- iconv(readBin(raw_data, character()), from="UTF-8", to="UTF-8")

# now the data can be read by any R function, eg.
read.csv(data)
fread(data)

# All this can be done without temporary objects:
fread(iconv(
  readBin(get_object('data.csv', 'my_bucket'), character()),
  from="UTF-8", to="UTF-8"))

据我所知,你所说的“签名URL”是不可用的。但如果你尝试开发这样的解决方案,则需要注意以下问题:在源代码中存储秘密访问密钥会带来安全风险。
此外,“签名URL”的另一个问题是对象将存储在内存中。如果工作区被保存,它将被存储在磁盘上。这样的解决方案需要仔细审查安全性。

1
抱歉 - 提前按了回车键。您担心这会创建一个临时文件?啊哈。据我从代码中所看到的,实际上并没有创建临时文件,但我可能错了。 s3load 调用 get_object(这里不会创建文件),get_object 调用 s3HTTP,仍然没有本地文件,该函数调用 httr 包中的 GET 方法。我看不到 awscli 的任何地方。 - pusillanimous
1
不好意思,那样行不通。没有办法将 AWS 文件的 URL 与身份验证一起存储。身份验证是通过将签名(由 signature_v4_auth 方法创建)作为 头部 与 GET 请求一起发送来实现的。因此,请求看起来像这样(不完全相同,但重点很清楚):GET /bucket/filename; Authentication: AUTH TOKEN HERE。您的想法存在问题,即 URL 与身份验证令牌是分开的,无法作为单个对象存储。(对格式造成的困扰深感抱歉) - pusillanimous
再详细解释一下:URL是统一资源定位符。它指定了对象(文件)的位置。您的登录信息不属于其中,因为它是关于状态的信息。为了允许无密码登录,AWS采用了令牌认证。这意味着程序可以通过发送用户ID和密钥来请求一个(有时限的)令牌。该令牌随后作为头部的元信息与每个请求一起发送。 - pusillanimous
我收到了以下错误信息: Error in fread(get_object(my_url, my_bucket)) : 'input' 必须是单个字符字符串,包含文件名、命令、文件的完整路径、以 'http[s]://', 'ftp[s]://' 或 'file://' 开头的 URL,或输入数据本身 - Bulat
2
这是因为get_object返回的是一个原始向量,而不是字符向量或连接。你可以这样做,尽管有点复杂:fread(iconv(readBin(get_object(url, bucket), character()), from = "UTF-8", to = "UTF-8"))(将from="UTF-8"替换为适当的编码)。 - pusillanimous
显示剩余7条评论

0
有点晚了,但也可以使用aws.s3包来实现以下功能:
data <- s3read_using(FUN = data.table::fread,
                     bucket = "my_bucket",
                     object = "path/to/file.csv")

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接