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

Python-Flask+boto3上传1-3MB图片至Amazon S3耗时16-18秒,求优化建议

Hey there! Let's figure out why your 1-3MB image uploads to S3 are taking 16-18 seconds—way longer than they should be. I'll walk through common configuration oversights and optimizations you can apply right away.

First, let's recap your setup for clarity:

  • Frontend: A basic file input with preview using readAsDataURL, paired with a form targeting your Flask endpoint.
  • Backend: A Flask route using boto3.client.upload_fileobj to send files directly to S3.

Your Current Code (Formatted)

Frontend

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form id="upload_form" action="/updateuser" method="POST" enctype="multipart/form-data">
  <label for="file">Choose file</label>
  <input type="file" id="fileinput" />
  <img id="source_image">
  <input type="button" id="upload" value="uploadimage">
</form>

<script>
function readFile(evt) { 
  var file = evt.target.files[0]; 
  var reader = new FileReader(); 
  output_format = "jpg"; 
  reader.onload = function(event) { 
    var i = document.getElementById("source_image"); 
    i.src = event.target.result; 
    i.onload = function(){ 
      image_width=$(i).width(), image_height=$(i).height(); 
      if(image_width > image_height){ 
        i.style.width="320px"; 
      }else{ 
        i.style.height="300px"; 
      } 
      i.style.display = "block"; 
      console.log("Image loaded"); 
    } 
  }; 
  console.log("Filename:" + file.name); 
  console.log("Filesize:" + (parseInt(file.size) / 1024) + " Kb"); 
  console.log("Type:" + file.type); 
  reader.readAsDataURL(file); 
  return false; 
} 
document.getElementById('fileinput').addEventListener('change', readFile, false);
</script>

Backend

import boto3
import time
from flask import Flask, request
from config import S3_KEY, S3_SECRET, S3_BUCKET

app = Flask(__name__)

# Ajax function to support upload image call from UI
@app.route('/user/uploadimage',methods=['GET','POST'])
def uploadimage():
    print("In uploadimage()")
    starttime = int(round(time.time() * 1000))
    print("Start Monitoring uploadimage()", starttime)
    try:
        s3 = boto3.client(
            "s3",
            aws_access_key_id=S3_KEY,
            aws_secret_access_key=S3_SECRET
        )
    except Exception as e:
        print(str(e))
    try:
        file = request.files['file']
        s3.upload_fileobj(
            file,
            S3_BUCKET,
            file.filename,
            ExtraArgs={
                "ACL": "public-read",
                "ContentType": file.content_type
            }
        )
        print("File uploaded successfully")
        print("Stop Monitoring uploadimage()", (int(round(time.time() * 1000)) - starttime))
    except Exception as e:
        print("Error while Saving Image on Amazon S3 : ", e)

Key Optimizations to Fix Slow Uploads

1. Specify Your S3 Bucket's Region in Boto3

By default, boto3 uses us-east-1 as the default region. If your S3 bucket is in a different region (e.g., eu-west-1, ap-southeast-1), this forces cross-region data transfer which adds massive latency.

Fix this by adding the region_name parameter when creating the S3 client:

s3 = boto3.client(
    "s3",
    aws_access_key_id=S3_KEY,
    aws_secret_access_key=S3_SECRET,
    region_name='ap-southeast-1'  # Replace with your bucket's actual region
)

2. Enable S3 Transfer Acceleration

Transfer Acceleration routes your uploads through CloudFront's global edge network, drastically reducing latency for users/servers far from your bucket's region.

First, enable Transfer Acceleration in your S3 bucket's settings (AWS Console > S3 > Your Bucket > Properties > Transfer Acceleration). Then update your Boto3 client to use the accelerated endpoint:

s3 = boto3.client(
    "s3",
    aws_access_key_id=S3_KEY,
    aws_secret_access_key=S3_SECRET,
    region_name='ap-southeast-1',
    endpoint_url=f'https://{S3_BUCKET}.s3-accelerate.amazonaws.com'
)

3. Optimize Boto3 Transfer Configuration

Tweak boto3's transfer settings to use parallel threads and smaller chunk sizes (even for sub-8MB files, which use single-part upload by default). This improves throughput over slow connections.

Add a TransferConfig when calling upload_fileobj:

from boto3.s3.transfer import TransferConfig

# Configure transfer settings
transfer_config = TransferConfig(
    multipart_threshold=1024 * 256,  # Use multipart for files >256KB
    max_concurrency=10,              # Number of parallel threads
    multipart_chunksize=1024 * 256,  # Chunk size per thread
    use_threads=True                 # Enable parallel transfers
)

# Use the config in your upload
s3.upload_fileobj(
    file,
    S3_BUCKET,
    file.filename,
    ExtraArgs={"ACL": "public-read", "ContentType": file.content_type},
    Config=transfer_config
)

4. Fix Frontend Upload Logic (Avoid Unnecessary Encoding)

Your frontend uses readAsDataURL for preview, which is fine—but make sure you're uploading the original file (not the base64-encoded version). If you're using AJAX to submit (since your form has a button instead of a submit input), use FormData to send the raw file efficiently:

Add this script for your upload button:

document.getElementById('upload').addEventListener('click', function() {
    const fileInput = document.getElementById('fileinput');
    const file = fileInput.files[0];
    if (!file) {
        alert("Please select a file first!");
        return;
    }

    const formData = new FormData();
    formData.append('file', file);

    fetch('/user/uploadimage', {
        method: 'POST',
        body: formData
    })
    .then(response => {
        if (response.ok) {
            console.log("Upload successful!");
            // Add success UI updates here
        } else {
            throw new Error("Upload failed");
        }
    })
    .catch(error => console.error("Error during upload:", error));
});

5. Check Server-to-S3 Network Path

  • If your Flask app is running on AWS EC2: Use an S3 VPC Endpoint to route traffic directly within AWS's private network (no public internet hop). This eliminates external latency and reduces costs.
  • If your server is outside AWS: Ensure your server has sufficient upload bandwidth. A 3MB file taking 18 seconds implies ~1.7Mbps speed—way below typical broadband. Contact your hosting provider if this is unexpected.

6. Update Boto3 and Botocore

Older versions of boto3 and botocore can have performance bugs or lack optimizations. Upgrade to the latest versions:

pip install --upgrade boto3 botocore

Final Notes

Start with the region fix first—it's the most common culprit for slow S3 uploads. Then test Transfer Acceleration if you're uploading from a location far from your bucket's region.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 04:24:16