有没有办法 touch() Amazon S3 中的文件?
Posted
技术标签:
【中文标题】有没有办法 touch() Amazon S3 中的文件?【英文标题】:Is there a way to touch() a file in Amazon S3? 【发布时间】:2012-11-07 10:56:05 【问题描述】:我目前正在使用Amazon S3,我正在编写一个使用修改后日期的程序。我正在寻找一种方法来编辑修改后的日期。
我可以遍历所有文件并按原样保存它们,但这听起来是个糟糕的解决方案。
在 php 中有这个函数touch()。
有没有人知道解决方案,或者有同样的问题?
【问题讨论】:
【参考方案1】:回应@Daniel Golden 对@tkotisis 回答的评论。看起来至少 AWS CLI 工具不允许您将项目复制到自身。但是,您可以通过更新元数据来“强制”复制。
$ aws s3 cp --metadata '"touched":"now"' s3://path/to/object s3://path/to/object
这会重新创建对象(下载到调用者并重新上传)替换其内容、所有者和元数据。这也会触发任何附加的 Lambda 事件。
【讨论】:
这会导致错误:fatal error: An error occurred (404) when calling the HeadObject operation: Key "index.html" does not exist
。【参考方案2】:
您可以通过copy object 请求实现相同的目的,指定 CopySource 与目标键相同。
本质上,这将向 S3 发出 PUT Object - COPY 请求,并带有相应的源和目标存储桶/密钥。
【讨论】:
你知道这到底是做什么的吗?它会为每个文件触发 GET 和 PUT 请求吗? 编辑了我的答案以包含此信息。 在运行此命令时:s3cmd cp s3://path/to/file s3://path/to/file
两条路径相同,我收到此错误:ERROR: S3 error: 400 (InvalidRequest): This copy request is illegal because it is trying to copy an object to itself without changing the object's metadata, storage class, website redirect location or encryption attributes.
@DanielGolden 您是否将x-amz-metadata-directive
请求标头设置为REPLACE
,如文档中所述?
这行得通 - 谢谢。 aws s3 cp s3://path/to/file s3://path/to/file --metadata-directive REPLACE
【参考方案3】:
这是将空(或 o 字节)文件上传到 S3 的另一个原因。我验证了这个工作您也可以使用 S3 API 上传没有正文的文件,如下所示:
aws s3api put-object --bucket "myBucketName" --key "dir-1/my_null_file"
通常您会指定一个--body
blob,但它的选项只会按预期添加密钥。查看更多关于S3 API put-object
测试的 AWS CLI 版本是:aws-cli/2.0.4 Python/3.7.5 Windows/10 botocore/2.0.0dev8
这是我在 PHP 中的做法(即使在过时的 5.4 中也可以使用,不得不退回):
// Init an S3Client
$awsConfig = $app->config('aws');
$aws = Aws::factory($awsConfig);
$s3Bucket = $app->config('S3_Bucket');
$s3Client = $aws->get('s3');
// Set null/empty file.
$result = $s3Client->putObject([
'Bucket' => $s3Bucket,
'Key' => "dir-1/my_null_file",
'Body' => '',
'ServerSideEncryption' => 'AES256',
]);
【讨论】:
最后,一个对我有用的答案!谢谢!【参考方案4】:我发现自己在测试时经常使用复制技巧,以至于我在我的 .bashrc 中添加了一个方便的功能:
s3-touch()
aws s3 cp \
--metadata 'touched=touched' \
--recursive --exclude="*" \
--include="$2" \
"$@:3" \
"$1" "$1"
示例用法:
# will do a dryrun on a copy operation
s3-touch s3://bucket/prefix/ "20200311*" --dryrun
# the real thing, creating events for all objects
# in s3://bucket/prefix/ that start with 20200311
s3-touch s3://bucket/prefix/ "20200311*"
我这样做主要是为了我想要触发的 S3 事件。
【讨论】:
【参考方案5】:在@g-io 回答简化了我的一天之后,这里有另一个版本,可以轻松触摸单个文件
s3-touch-single()
aws s3 cp \
--metadata 'touched=touched' \
"$@:3" \
"$1" "$1"
例如,循环我们需要触摸的文件数组:
paths=("mydir/image.png" "mydir2/image2.png")
for i in "$paths[@]"; do s3-touch-single "s3://my-bucket/$i"; done
【讨论】:
酷有没有办法用 java api 做到这一点? 问:第 4 行应该是 "$@:2" 还是我遗漏的第二个参数? @Stormcloud 老实说我不记得为什么了,现在看脚本时看起来确实是多余的 @peterk 您可以以类似的方式使用 java sdk(仅使用 java 而不是 bash)。它可能在后端使用相同的 API。 @BenYitzhaki 有趣的是,我尝试这样做是更改元数据中的一个字段,然后使用新的元数据将对象复制到自身。这确实会更改元数据,但不会在后续访问时更改 summary.getLastModified() 值。【参考方案6】:查看https://github.com/emdgroup/awscli-s3touch
它是 AWS CLI 的插件,可添加 touch
命令。
用法:
aws s3 touch my-bucket --prefix myfolder/
它通过读取附加到存储桶的事件并在客户端模拟它们来工作。
【讨论】:
阅读源代码,该插件只是触发一旦PUT操作发生就应该触发的事件,而没有实际接触文件。误导性回购名称以上是关于有没有办法 touch() Amazon S3 中的文件?的主要内容,如果未能解决你的问题,请参考以下文章
将数据从 Amazon S3 复制到 Redshift 并避免重复行
对 Amazon S3 存储桶的 FTP/SFTP 访问 [关闭]