引入 boto3 框架

前置步骤:安装框架(https://boto3.amazonaws.com/v1/documentation/api/latest/guide/quickstart.html

s4-demo.py
# import
import boto3
from botocore.client import Config

# Config
s3endpoint = 'https://s3.bitiful.net' # 请填入控制台 “Bucket 设置” 页面底部的 “Endpoint” 标签中的信息
s3region = 'cn-east-1'
s3accessKeyId = '子账户 accessKey' # 请到控制台创建子账户,并为子账户创建相应 accessKey
s3SecretKeyId = '子账户 secretKey' # !!切记,创建子账户时,需要手动为其分配具体权限!!

连接到 S4 Endpoint

s4-demo.py
    s3client = boto3.client(
        's3',
        aws_access_key_id = s3accessKeyId,
        aws_secret_access_key = s3SecretKeyId,
        endpoint_url = s3endpoint,
        region_name = s3region
     )

列出桶中对象

s4-demo.py
    buckets = s3client.list_buckets()
    for bucket in buckets['Buckets']:
        print(bucket["Name"])

用 Python 调用 S3 SDK(Boto3)实现一个下发“PutObject 预签名链接”以供 Web JS(axios 发起 PUT 请求)上传的前后端完整例子:

s4-demo.py
import boto3
from flask import Flask
from flask import render_template_string
from flask import request

app = Flask(__name__)


@app.get('/upload_url')
def get_upload_url():
    # Config
    s3endpoint = 'https://s3.bitiful.net' # 请填入控制台 “Bucket 设置” 页面底部的 “Endpoint” 标签中的信息
    s3region = 'cn-east-1'
    s3accessKeyId = '子账户 accessKey' # 请到控制台创建子账户,并为子账户创建相应 accessKey
    s3SecretKeyId = '子账户 secretKey' # !!切记,创建子账户时,需要手动为其分配具体权限!!

    # 连接 S3
    client = boto3.client(
        's3',
        aws_access_key_id = s3accessKeyId,
        aws_secret_access_key = s3SecretKeyId,
        endpoint_url = s3endpoint,
        region_name = s3region
    )
    url = client.generate_presigned_url(
        'put_object',
        Params={
            'Bucket': 'xxxxxx',
            'Key': request.args.get('key'),
        },
        ExpiresIn=3600
    )
    return {'url': url}


@app.get('/')
def index():
    return render_template_string('''
<!DOCTYPE html>
<html>
<head>
  <title>S3 File Upload</title>
</head>
<body>
<div>
  <h1>S3 File Upload</h1>
  <input type="file" id="file">
  <button onclick="handleClick()">Upload</button>
</div>
<script src="https://cdn.bootcdn.net/ajax/libs/axios/1.3.6/axios.min.js"></script>
<script>
    let file;
    let fileContent;

    const fileInput = document.getElementById('file');
    const fileReader = new FileReader();

    fileInput.addEventListener('change', function (event) {
        file = event.target.files[0];
        console.log("file is: ", file);
        fileReader.readAsArrayBuffer(file);
    });

    fileReader.onload = function (event) {
        fileContent = event.target.result;
        // console.log("fileContent is: ", fileContent);
    };

    function handleClick() {
        console.log('click');

        const url = `/upload_url`;
        const params = {key: '1.jpg'};

        axios.get(url, {params: params})
            .then(function (res) {
                console.log(res);
                const url = res.data.url;
                const config = {
                    headers: {
                        'Content-Type': null,
                    },
                };
                axios.put(url, file, config)
                    .then(function (res) {
                        console.log("res is: ", res);
                    });
            });

    }
</script>

</body>
</html>    
''')

if __name__ == '__main__':
    app.run(debug=True)