You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

S3文件夹预签名URL无法批量下载文件,如何解决?

解决S3文件夹批量生成预签名URL共享的问题

首先得说清楚为啥你遇到这个情况:AWS S3本质上没有真正的「文件夹」,所谓的文件夹只是对象的前缀而已。你直接给s3://bucket-name/large-folder/生成预签名URL时,CLI其实是给这个不存在的「虚拟文件夹对象」签了权,所以下载到的是0字节空文件,而单个文件的URL正常是因为指向了实际存在的对象。

下面给你几个可行的解决办法:

方法1:批量生成每个文件的预签名URL

用AWS CLI遍历文件夹下所有文件,逐个生成预签名URL,把这些URL整理到一个文本文件里共享给对方就行。

直接在云Shell里执行这个命令:

aws s3 ls s3://bucket-name/large-folder/ --recursive | awk '{print $4}' | while read file; do
  if [ -n "$file" ]; then
    echo "$(aws s3 presign s3://bucket-name/$file --expires-in 604800 --region us-east-1) -> $file"
  fi
done > presigned_urls.txt

执行完后,当前目录会生成presigned_urls.txt,里面每行都是一个文件的预签名URL和对应的文件名,把这个文件发给外部用户,他们就能逐个下载文件了。

方法2:把整个文件夹打包成ZIP再生成预签名URL

如果想让用户一次性下载所有文件,最方便的是把文件夹内容打包成ZIP,再给这个ZIP文件生成预签名URL。

适合小体量文件夹的云Shell直接打包

如果文件夹总文件大小不大(云Shell有存储和带宽限制),直接用下面的命令:

# 把文件夹内容打包成ZIP并上传到S3临时路径
aws s3 cp s3://bucket-name/large-folder/ - --recursive | zip -r - large-folder/ > large-folder.zip
aws s3 cp large-folder.zip s3://bucket-name/temp/large-folder.zip

# 给这个ZIP生成预签名URL
aws s3 presign s3://bucket-name/temp/large-folder.zip --expires-in 604800 --region us-east-1

执行完后会输出ZIP文件的预签名URL,用户下载这个ZIP就能得到所有Parquet文件了。记得之后可以删掉临时的ZIP文件节省存储。

适合大文件夹的Lambda打包方案

如果文件夹里文件太多、总容量大,云Shell搞不定,就用Lambda来生成ZIP:

  • 新建一个Python Lambda函数,区域选us-east-1,权限给足S3的读写权限。
  • 把下面的代码粘贴进去,替换bucket和prefix的值:
import boto3
import zipfile
from io import BytesIO

s3 = boto3.client('s3', region_name='us-east-1')
bucket = 'bucket-name'  # 替换成你的存储桶名
prefix = 'large-folder/'  # 替换成目标文件夹前缀
temp_zip_key = 'temp/large-folder.zip'  # 临时ZIP文件的存储路径

# 内存中打包文件
zip_buffer = BytesIO()
with zipfile.ZipFile(zip_buffer, 'w', zipfile.ZIP_DEFLATED) as zf:
    # 分页遍历S3前缀下的所有文件
    paginator = s3.get_paginator('list_objects_v2')
    for page in paginator.paginate(Bucket=bucket, Prefix=prefix):
        for obj in page.get('Contents', []):
            # 跳过虚拟文件夹本身
            if obj['Key'] == prefix:
                continue
            # 获取文件内容并写入ZIP
            obj_data = s3.get_object(Bucket=bucket, Key=obj['Key'])
            # 去掉前缀,保留文件相对路径
            zf.writestr(obj['Key'].replace(prefix, ''), obj_data['Body'].read())

# 把ZIP上传回S3
zip_buffer.seek(0)
s3.put_object(Bucket=bucket, Key=temp_zip_key, Body=zip_buffer)

# 生成预签名URL
presigned_url = s3.generate_presigned_url('get_object',
    Params={'Bucket': bucket, 'Key': temp_zip_key},
    ExpiresIn=604800)

print(presigned_url)
  • 执行Lambda函数,控制台会输出ZIP文件的预签名URL,用户下载这个URL就能拿到所有文件了。

方法3:启用静态网站托管共享文件列表(需配置权限)

如果你的存储桶可以开启静态网站托管,也可以通过这种方式让用户看到文件列表并下载:

  • 登录S3控制台,找到你的存储桶,开启「静态网站托管」,设置索引文档(比如index.html)。
  • 给存储桶配置权限,允许外部用户的s3:GetObject和s3:ListBucket操作。
  • 生成静态网站前缀的预签名URL:
aws s3 presign https://bucket-name.s3-website-us-east-1.amazonaws.com/large-folder/ --expires-in 604800 --region us-east-1

用户访问这个URL会看到文件夹下的所有文件列表,点击就能下载(前提是每个文件也有对应的访问权限,或者你也可以给每个文件批量生成预签名URL放在列表里)。不过这种方式配置相对麻烦,不如前两种直接。

内容的提问来源于stack exchange,提问作者Ritab

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 18:23:19