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

使用Boto3向S3复制文件时,如何避免覆盖已存在文件?

解决S3同名文件重复上传覆盖的问题

问题根源

你的代码逻辑完全搞反了:遍历S3桶内的每一个对象时,只要当前对象的key和目标文件名fn2不一致,就执行上传操作。这意味着只要桶里有任何一个和fn2不同的文件,代码就会触发上传,直接覆盖掉已经存在的同名文件,完全达不到“仅当无同名文件时上传”的要求。

修复方案

方案1:高效检查文件是否存在(推荐)

使用boto3的head_object方法直接检查目标文件是否存在,比遍历所有对象效率高得多,尤其适合文件数量多的桶:

import boto3
import botocore
import glob
import os

exchanges = ["bats"]

for ex in exchanges:
    # 获取最新CSV文件
    csv_file_list = glob.glob(f"H:\SQL_EXPORTS\eod\candles\{ex}\\*.csv")
    latest_file = max(csv_file_list, key=os.path.getctime)
    
    # 整理文件信息(无需手动拼接路径,直接用现成的latest_file)
    local_file_path = latest_file
    s3_file_key = os.path.basename(latest_file)
    
    print(f"待处理文件: {s3_file_key}")
    
    # 初始化S3客户端
    s3_client = boto3.client('s3')
    bucket_name = f'eod-candles-{ex}'
    
    # 检查文件是否存在于S3桶
    try:
        s3_client.head_object(Bucket=bucket_name, Key=s3_file_key)
        print(f"文件 {s3_file_key} 已存在,跳过上传")
    except botocore.exceptions.ClientError as e:
        if e.response['Error']['Code'] == '404':
            # 文件不存在,执行上传
            s3_client.upload_file(local_file_path, bucket_name, s3_file_key)
            print(f"文件 {s3_file_key} 上传成功")
        else:
            # 处理其他异常(比如权限不足)
            print(f"检查文件时出错: {str(e)}")

方案2:遍历对象列表检查(适合小桶)

如果坚持用遍历桶对象的方式,必须先收集所有文件的key,再统一判断,而不是遍历每个对象时都执行上传:

import boto3
import glob
import os

exchanges = ["bats"]

for ex in exchanges:
    csv_file_list = glob.glob(f"H:\SQL_EXPORTS\eod\candles\{ex}\\*.csv")
    latest_file = max(csv_file_list, key=os.path.getctime)
    
    local_file_path = latest_file
    s3_file_key = os.path.basename(latest_file)
    
    print(f"待处理文件: {s3_file_key}")
    
    s3 = boto3.resource('s3')
    bucket_name = f'eod-candles-{ex}'
    my_bucket = s3.Bucket(bucket_name)
    
    # 收集桶内所有文件的key
    existing_file_keys = [obj.key for obj in my_bucket.objects.all()]
    
    if s3_file_key not in existing_file_keys:
        s3.meta.client.upload_file(local_file_path, bucket_name, s3_file_key)
        print(f"文件 {s3_file_key} 上传成功")
    else:
        print(f"文件 {s3_file_key} 已存在,跳过上传")

额外优化点

  • 删掉重复导入的os模块
  • 无需手动拼接文件路径,latest_file已经是完整本地路径,直接使用即可
  • 执行简单操作时,s3_client比s3.resource更简洁

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 09:01:12