【问题标题】:Is there a way to touch() a file in Amazon S3?有没有办法 touch() Amazon S3 中的文件?
【发布时间】:2012-11-07 10:56:05
【问题描述】:

我目前正在使用Amazon S3,我正在编写一个使用修改后日期的程序。我正在寻找一种方法来编辑修改后的日期。

我可以遍历所有文件并按原样保存它们,但这听起来是个糟糕的解决方案。

在 PHP 中有这个函数touch()

有没有人知道解决方案,或者有同样的问题?

【问题讨论】:

    标签: amazon-s3 metadata last-modified


    【解决方案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操作发生就应该触发的事件,而没有实际接触文件。误导性回购名称
      猜你喜欢
      • 1970-01-01
      • 2011-09-10
      • 1970-01-01
      • 1970-01-01
      • 2016-12-05
      • 1970-01-01
      • 2015-07-30
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多