有没有办法 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 访问 [关闭]

PHP 将远程图像保存到 Amazon S3

我们如何为 Amazon S3 存储桶中的文件夹设置 CORS

如何(批量)删除Amazon S3存储桶中几百个文件的列表

从 Amazon S3 流式传输 MP3