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

Python中识别S3中新上传文件的最简方法(存在旧文件覆盖场景)

最简识别新增FTP文件的方案

这问题我做FTP到S3同步的时候也踩过坑,之前傻乎乎全量下载覆盖,既费带宽又慢。结合你的场景,给你两个最省心的方案,按最简程度排序:

方案1:直接对比S3已存文件列表(零额外存储,首选)

既然你是把文件上传到S3的同一路径,那最直接的办法就是先拉取S3桶里已有的所有文件名,再和FTP上的文件列表做差集,只处理S3里没有的文件。完全不需要额外存任何记录,利用S3本身的对象列表就行。

代码示例(用boto3实现)

import boto3
from ftplib import FTP

# 初始化S3客户端(确保本地配置了AWS凭证,或者通过环境变量传入)
s3 = boto3.client('s3')
BUCKET_NAME = 'your-target-bucket'

def get_existing_s3_files():
    """获取S3桶中已有的所有文件Key"""
    existing_keys = set()
    # 处理S3分页(如果文件多的话必须用分页)
    paginator = s3.get_paginator('list_objects_v2')
    for page in paginator.paginate(Bucket=BUCKET_NAME):
        if 'Contents' in page:
            for obj in page['Contents']:
                existing_keys.add(obj['Key'])
    return existing_keys

def get_sorted_ftp_files(ftp_host, ftp_user, ftp_pass, remote_dir):
    """从FTP获取按时间戳升序排列的文件列表"""
    ftp = FTP(ftp_host)
    ftp.login(ftp_user, ftp_pass)
    ftp.cwd(remote_dir)
    
    # 假设文件名包含时间戳(比如file_202405201430),按时间戳排序
    # 如果你的文件名本身就是按时间戳命名的,直接sorted()就行
    ftp_files = ftp.nlst()
    sorted_files = sorted(ftp_files, key=lambda x: x.split('_')[-1])
    
    ftp.quit()
    return sorted_files

# 主同步逻辑
if __name__ == "__main__":
    existing_files = get_existing_s3_files()
    ftp_files = get_sorted_ftp_files('your-ftp-host', 'ftp-user', 'ftp-pass', '/remote/files')
    
    # 只处理S3中没有的新增文件
    for file in ftp_files:
        if file not in existing_files:
            print(f"发现新增文件,开始处理:{file}")
            # 这里填入你的FTP下载代码,比如:
            # download_ftp_file(file)
            # 然后上传到S3:
            # s3.upload_file(f'/local/tmp/{file}', BUCKET_NAME, file)

方案2:用S3存储已处理文件记录(适合文件名可能重复的场景)

如果你的FTP文件名可能存在重复(比如后续会出现同名但内容不同的文件),或者担心S3文件被误删导致重复处理,那可以在S3里存一个简单的元数据文件(比如processed_files.txt),记录所有已经处理过的文件名。每次运行前下载这个文件,对比FTP列表,处理完新文件后更新记录再上传回去。

代码示例

def get_processed_files():
    """从S3获取已处理的文件列表"""
    try:
        # 下载记录文件到本地临时目录
        s3.download_file(BUCKET_NAME, 'processed_files.txt', '/tmp/processed.txt')
        with open('/tmp/processed.txt', 'r') as f:
            return set(f.read().splitlines())
    except s3.exceptions.NoSuchKey:
        # 如果记录文件不存在,返回空集合
        return set()

def update_processed_files(processed_files):
    """更新S3中的已处理文件记录"""
    with open('/tmp/processed.txt', 'w') as f:
        f.write('\n'.join(processed_files))
    s3.upload_file('/tmp/processed.txt', BUCKET_NAME, 'processed_files.txt')

# 主逻辑
if __name__ == "__main__":
    processed_files = get_processed_files()
    ftp_files = get_sorted_ftp_files('your-ftp-host', 'ftp-user', 'ftp-pass', '/remote/files')
    
    new_files = [f for f in ftp_files if f not in processed_files]
    for file in new_files:
        print(f"处理新增文件:{file}")
        # 下载+上传代码...
        processed_files.add(file)
    
    # 更新已处理记录
    update_processed_files(processed_files)

额外小提示

如果你的FTP服务器支持MDTM命令(可以获取文件的修改时间),也可以通过对比文件修改时间来识别新增/更新的文件,但这个需要记录上次同步的时间,复杂度比前两个方案高一些。除非你的文件名里的时间戳不可靠,否则优先用前两个方案。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 10:57:27