有没有办法使用 AWS CLI 获取 S3 对象的位置 (public url)?

Is there a way to get location (public url) of S3 object using AWS CLI?

<前提>
我总体上是新的云计算,特别是 AWS 和 REST API,我正在尝试拼凑一个 "big-picture" 的理解。

我正在使用 LocalStack - 据我所知,它通过对 AWS API 的(子集)做出相同的响应来模拟真实的 AWS if您指定 LocalStack 侦听的端点 address/port。

最后,我一直在学习本教程:https://dev.to/goodidea/how-to-fake-aws-locally-with-localstack-27me

使用提到的教程并根据其指导,我使用 AWS CLI 成功创建了一个 S3 存储桶。
不过,为了演示将本地文件上传到 S3 存储桶,本教程切换到 node.js,我认为它演示了 AWS node.js SDK:

# aws.js
# This code segment comes from https://dev.to/goodidea/how-to-fake-aws-locally-with-localstack-27me
#

const AWS = require('aws-sdk')
require('dotenv').config()

const credentials = {
   accessKeyId: process.env.AWS_ACCESS_KEY_ID,
   secretAccessKey: process.env.AWS_SECRET_KEY,
}

const useLocal = process.env.NODE_ENV !== 'production'

const bucketName = process.env.AWS_BUCKET_NAME

const s3client = new AWS.S3({
   credentials,
   /**
    * When working locally, we'll use the Localstack endpoints. This is the one for S3.
    * A full list of endpoints for each service can be found in the Localstack docs.
    */
   endpoint: useLocal ? 'http://localhost:4572' : undefined,
   /**
     * Including this option gets localstack to more closely match the defaults for
     * live S3. If you omit this, you will need to add the bucketName to the `Key`
     * property in the upload function below.
     *
     * see: https://github.com/localstack/localstack/issues/1180
     */
   s3ForcePathStyle: true,
})


const uploadFile = async (data, fileName) =>
   new Promise((resolve) => {
      s3client.upload(
         {
            Bucket: bucketName,
            Key: fileName,
            Body: data,
         },
         (err, response) => {
            if (err) throw err
            resolve(response)
         },
      )
   })

module.exports = uploadFile

.

# test-upload.js
# This code segment comes from https://dev.to/goodidea/how-to-fake-aws-locally-with-localstack-27me
#

const fs = require('fs')
const path = require('path')
const uploadFile = require('./aws')

const testUpload = () => {
   const filePath = path.resolve(__dirname, 'test-image.jpg')
   const fileStream = fs.createReadStream(filePath)
   const now = new Date()
   const fileName = `test-image-${now.toISOString()}.jpg`
   uploadFile(fileStream, fileName).then((response) => {
      console.log(":)")
      console.log(response)
   }).catch((err) => {
      console.log(":|")
      console.log(err)
   })
}

testUpload()

调用:

$ node test-upload.js
:)
{ ETag: '"c6b9e5b1863cd01d3962c9385a9281d"',
  Location: 'http://demo-bucket.localhost:4572/demo-bucket/test-image-2019-03-11T21%3A22%3A43.511Z.jpg',
  key: 'demo-bucket/test-image-2019-03-11T21:22:43.511Z.jpg',
  Key: 'demo-bucket/test-image-2019-03-11T21:22:43.511Z.jpg',
  Bucket: 'demo-bucket' }

我之前没有使用过node.js,但是我对上面代码的理解是,它使用了AWS.S3.upload() AWS node.js SDK方法来复制一个本地文件到 S3 存储桶,并打印 HTTP 响应(正确吗?)。

问题:我观察到 HTTP 响应包含一个 "Location" 键,其值看起来像 URL 我可以 copy/paste 进入浏览器以直接从 S3 存储桶中查看图像;有没有办法使用 AWS CLI 获取此位置?

我假设 AWS CLI 命令是 AWS SDK 的类似物是否正确?

我尝试使用 aws s3 cp CLI 命令将文件上传到我的 S3 存储桶,我认为这类似于上面的 AWS.S3.upload() 方法,但它没有生成任何输出,并且我不确定我应该做什么 - 或者应该做什么 - 以 HTTP 对 AWS.S3.upload() AWS 节点 SDK 方法的响应方式获取位置。

$ aws --endpoint-url=http://localhost:4572 s3 cp ./myFile.json s3://myBucket/myFile.json
upload: ./myFile.json to s3://myBucket/myFile.json

更新:继续研究让我现在想知道上传到 S3 存储桶的文件是否 隐式 任何方式 - 无论是通过 CLI 命令 aws s3 cp 还是 node.js SDK 方法 AWS.S3.upload() 等 - 都可以在 http://<bucket_name>.<endpoint_without_http_prefix>/<bucket_name>/<key> 访问?例如。 http://myBucket.localhost:4572/myBucket/myFile.json?
如果这是 隐含的 ,我想你可能会争辩说没有必要像那个例子 node.js HTTP 响应那样给定 "Location"。
感谢您的指导 - 我希望很明显我在所有相关技术上的教育程度很低。


更新 2:看起来正确的 url 是 <endpoint>/<bucket_name>/<key>,例如http://localhost:4572/myBucket/myFile.json.

A​​WS CLI 和不同的 SDK 提供相似的功能,但有些会添加额外的功能,有些会以不同的方式设置数据格式。可以安全地假设您可以执行 CLI 使用 SDK 执行的操作,反之亦然。有时你可能只需要为它工作一点。

正如您在更新中所说,并非每个上传到 S3 的文件都 public 可用。桶有策略,文件有权限。如果策略和权限允许,文件仅 public 可用。

如果文件是 public 那么您可以按照您的描述构造 URL。如果您有用于网站托管的存储桶设置,您还可以使用您设置的域。

但是如果文件不是 public 或者您只是想要一个临时文件 URL,您可以使用 aws presign s3://myBucket/myFile.json。这会给你一个 URL ,任何人都可以使用它来下载具有执行命令的人的权限的文件。 URL 的有效期为一小时,除非您使用 --expires-in 选择不同的时间。 SDK 也有类似的功能,但您需要稍微努力才能使用它。

注意:从版本 0.11.0 开始,所有 API 都通过单个边缘服务公开,默认情况下可在 http://localhost:4566 上访问。

考虑到您已将一些文件添加到存储桶

aws --endpoint-url http://localhost:4566 s3api list-objects-v2 --bucket mybucket
{
    "Contents": [
        {
            "Key": "blog-logo.png",
            "LastModified": "2020-12-28T12:47:04.000Z",
            "ETag": "\"136f0e6acf81d2d836043930827d1cc0\"",
            "Size": 37774,
            "StorageClass": "STANDARD"
        }
    ]
}

您应该可以使用

访问您的文件

http://localhost:4566/mybucket/blog-logo.png