一、概述
RustFS 是一款兼容 Amazon S3 协议的对象存储服务,支持通过 Python 的Boto3SDK 接入。
本教程将讲解如何使用 Python 与 RustFS 进行集成,并通过 Boto3 完成如下操作:
- Bucket 创建/删除
- 对象上传/下载/删除
- 列举对象
- 生成预签名 URL
- 分片上传大文件
二、环境准备
2.1 RustFS 信息
假设 RustFS 部署如下:
Endpoint: http://192.168.1.100:9000AccessKey: rustfsadminSecretKey: rustfssecret
2.2 安装 Boto3
推荐使用venv虚拟环境:
python3 -m venv venvsource venv/bin/activatepip install boto3
Boto3 依赖botocore,会自动安装。
三、连接 RustFS
import boto3from botocore.client import Configs3 = boto3.client( 's3', endpoint_url='http://192.168.1.100:9000', aws_access_key_id='rustfsadmin', aws_secret_access_key='rustfssecret', config=Config(signature_version='s3v4'), region_name='us-east-1')
✅endpoint_url:指向 RustFS ✅signature_version='s3v4':RustFS 支持 v4 签名 ✅region_name:RustFS 不校验 region,填写任意值即可
四、基础操作
4.1 创建 Bucket
bucket_name = 'my-bucket'try: s3.create_bucket(Bucket=bucket_name) print(f'Bucket {bucket_name} created.')except s3.exceptions.BucketAlreadyOwnedByYou: print(f'Bucket {bucket_name} already exists.')
4.2 上传文件
s3.upload_file('hello.txt', bucket_name, 'hello.txt')print('File uploaded.')
4.3 下载文件
s3.download_file(bucket_name, 'hello.txt', 'hello-downloaded.txt')print('File downloaded.')
4.4 列出对象
response = s3.list_objects_v2(Bucket=bucket_name)for obj in response.get('Contents', []): print(f"- {obj['Key']} ({obj['Size']} bytes)")
4.5 删除对象与 Bucket
s3.delete_object(Bucket=bucket_name, Key='hello.txt')print('Object deleted.')s3.delete_bucket(Bucket=bucket_name)print('Bucket deleted.')
五、高级功能
5.1 生成预签名 URL
5.1.1 下载链接(GET)
url = s3.generate_presigned_url( ClientMethod='get_object', Params={'Bucket': bucket_name, 'Key': 'hello.txt'}, ExpiresIn=600 # 10 分钟有效期)print('Presigned GET URL:', url)
5.1.2 上传链接(PUT)
url = s3.generate_presigned_url( ClientMethod='put_object', Params={'Bucket': bucket_name, 'Key': 'upload-by-url.txt'}, ExpiresIn=600)print('Presigned PUT URL:', url)
你可以使用curl工具上传:
curl -X PUT --upload-file hello.txt "http://..."
5.2 分片上传(Multipart Upload)
适合大于 10 MB 文件上传,可手动控制每个分片。
import osfile_path = 'largefile.bin'key = 'largefile.bin'part_size = 5 * 1024 * 1024 # 5 MB# 1. 启动上传response = s3.create_multipart_upload(Bucket=bucket_name, Key=key)upload_id = response['UploadId']parts = []try: with open(file_path, 'rb') as f: part_number = 1 while True: data = f.read(part_size) if not data: break part = s3.upload_part( Bucket=bucket_name, Key=key, PartNumber=part_number, UploadId=upload_id, Body=data ) parts.append({'ETag': part['ETag'], 'PartNumber': part_number}) print(f'Uploaded part {part_number}') part_number += 1 # 2. 完成上传 s3.complete_multipart_upload( Bucket=bucket_name, Key=key, UploadId=upload_id, MultipartUpload={'Parts': parts} ) print('Multipart upload complete.')except Exception as e: # 中止上传 s3.abort_multipart_upload(Bucket=bucket_name, Key=key, UploadId=upload_id) print('Multipart upload aborted due to error:', e)
六、常见问题排查
问题 | 原因 | 解决方法 |
SignatureDoesNotMatch
| 未使用 v4 签名 | 设置signature_version='s3v4' |
EndpointConnectionError
| RustFS 地址错误或服务未启动 | 检查 endpoint 与 RustFS 服务状态 |
AccessDenied
| 凭证错误或权限不足 | 检查 AccessKey/SecretKey 或桶策略 |
PermanentRedirect
| 未启用 path-style | Boto3 默认使用 virtual-host,RustFS 仅支持 path-style,但设置 endpoint 可绕过 |
七、附录:快速上传/下载脚本模板
def upload_file(local_path, bucket, object_key): s3.upload_file(local_path, bucket, object_key) print(f"Uploaded {local_path} to s3://{bucket}/{object_key}")def download_file(bucket, object_key, local_path): s3.download_file(bucket, object_key, local_path) print(f"Downloaded s3://{bucket}/{object_key} to {local_path}")