繁体   English   中英

如何在 Amazon s3 Bucket 中压缩文件并获取其 URL

[英]How to zip files in Amazon s3 Bucket and get its URL

我在 Amazon s3 存储桶中有一堆文件,我想压缩这些文件并使用 Java Spring 通过 S3 URL 下载内容。

S3 不是文件服务器,也不提供操作系统文件服务,例如数据操作。

如果有很多“巨大”的文件,你最好的选择是

  1. 启动一个简单的 EC2 实例
  2. 将所有这些文件下载到 EC2 实例,压缩它们,使用新的对象名称将其重新上传回 S3 存储桶

是的,您可以使用 AWS lambda 来做同样的事情,但 lambda 被限制为 900 秒(15 分钟)执行超时(因此建议分配更多 RAM 以提高 lambda 执行性能)

从 S3 到本地区域 EC2 实例等服务的流量是免费的。

如果您的主要目的只是使用 EC2/etc 服务读取同一 AWS 区域内的那些文件,那么您不需要这个额外的步骤。 直接访问文件即可。

(更新):正如@Robert Reiz 所提到的,现在您也可以使用 AWS Fargate 来完成这项工作。

笔记 :

建议使用 AWS API 访问和共享文件。 如果您打算公开共享该文件,则必须认真研究安全问题并施加下载限制。 AWS 到互联网的流量从不便宜。

将它们压缩到您的末端,而不是在 AWS 中进行,最好是在前端,直接在用户浏览器上进行。 您可以在 javascript 中流式下载多个文件,使用该流创建一个 zip 并将此 zip 保存在用户磁盘上。

将 zipping 移到前端的优点:

  • 您可以将它与 S3 URL、一堆预签名链接一起使用,甚至可以混合来自不同来源的内容,一些来自 S3,一些来自其他任何地方。
  • 您不会浪费 lambda 内存,也不必启动 EC2 Fargate 实例,这样可以节省资金。 让用户计算机为您完成。
  • 改善用户体验 - 无需等待创建 zip 即可开始下载,只需在创建 zip 的同时开始下载。

StreamSaver对此很有用,但在他们的压缩示例( 将多个文件另存为 zip )中,由于它没有实现 zip64,因此文件数量少于 4GB。

如果您选择此选项,请记住,如果您在存储桶中启用了 CORS,则需要在存储桶的 CORS 配置的AllowedOrigins字段中添加完成压缩的前端 url。

如果您需要压缩 S3 中的单个文件(对象),则可以采用一种迂回的方式进行压缩。 您可以定义一个指向 S3 存储桶的 CloudFront 端点,然后让 CloudFront 在输出时压缩内容: https : //docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/ServingCompressedFiles.html

嗨,我最近必须为我的应用程序执行此操作 - 通过用户可以下载的 url 链接提供一组 zip 格式的文件。

简而言之,首先使用 BytesIO 方法创建一个对象,然后使用 ZipFile 方法通过迭代所有 s3 对象来写入这个对象,然后在这个 zip 对象上使用 put 方法并为其创建一个预设的 url。

我使用的代码如下所示:

首先调用这个函数获取zip对象,ObjectKeys就是你需要放入zip文件的s3对象。


def zipResults(bucketName, ObjectKeys):
    buffer = BytesIO()
    with zipfile.ZipFile(buffer, 'w', compression=zipfile.ZIP_DEFLATED) as zip_file:
        for ObjectKey in ObjectKeys:
            objectContent = S3Helper().readFromS3(bucketName, ObjectKey)
            fileName = os.path.basename(ObjectKey)
            zip_file.writestr(fileName, objectContent)

    buffer.seek(0)
    return buffer

然后调用这个函数,key 是你给你的 zip 对象的键:

def uploadObject(bucketName, body, key):
    s3client = AwsHelper().getClient("s3")
    try:
        response = s3client.put_object(
            Bucket=bucketName,
            Body=body,
            Key=key
        )
    except ClientError as e:
        logging.error(e)
        return None

    return response

当然,您需要 io、zipfile 和 boto3 模块。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM