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

如何解决ftplib.error_perm:550文件被占用导致的FTP上传失败问题

解决FTP上传时ftplib.error_perm: 550文件被占用的问题

看起来你遇到的这个550错误有点棘手,结合你提供的代码和场景,我来拆解下可能的原因并给出具体的解决办法~

错误原因分析

这个错误提示虽然说“文件被其他进程占用”,但在FTP上传场景下可能有几种诱因:

  • 本地端:图片文件还没完全写入磁盘(比如生成图片的进程还在flush数据)、被杀毒软件/其他工具扫描锁定
  • 服务器端:上次上传失败留下的残损文件被服务器进程占用、目标文件正在被其他操作处理
  • 网络问题:上传中途断连导致服务器端文件处于半打开状态

针对性解决方案

1. 确保本地文件可安全读取

你已经通过检查jpg结尾的\xff\xd9来验证文件完整性,但有时候即使结尾正确,文件可能还被其他进程占用。可以给文件读取加重试逻辑:

import time

def get_safe_file_handle(file_path, max_retries=3, retry_delay=1):
    """尝试多次获取文件句柄,处理本地文件占用问题"""
    for retry in range(max_retries):
        try:
            return open(file_path, 'rb')
        except PermissionError:
            print(f"文件 {file_path} 被占用,{retry_delay}秒后重试...")
            time.sleep(retry_delay)
    raise RuntimeError(f"多次尝试后仍无法打开文件:{file_path}")

2. 给FTP上传加重试机制(适配网络不稳定+服务器端占用)

针对上传过程中出现的550错误或网络中断,我们可以:

  • 重试上传前先尝试删除服务器上的目标文件(清理残损文件)
  • 捕获相关异常并自动重试
  • 连接断开时自动重新登录FTP

修改你的上传逻辑为带重试的函数:

import ftplib
import socket

def upload_with_retry(ftp, local_path, remote_filename, cut_switch, max_retries=3, retry_delay=2):
    """带重试的FTP上传函数"""
    for attempt in range(1, max_retries+1):
        try:
            # 先尝试删除服务器上可能存在的残损文件
            try:
                ftp.delete(remote_filename)
                print(f"已删除服务器上的旧文件:{remote_filename}")
            except ftplib.error_perm:
                # 文件不存在时忽略该错误
                pass

            # 执行上传逻辑
            print(f"第 {attempt} 次尝试上传:{remote_filename}")
            if cut_switch:
                img = Cut_image(local_path)
                ftp.storbinary(f'STOR {remote_filename}', img)
            else:
                with get_safe_file_handle(local_path) as imageReader:
                    ftp.storbinary(f'STOR {remote_filename}', imageReader)
            
            print(f"上传成功:{remote_filename}")
            return True
        
        except (ftplib.error_perm, socket.error, ConnectionResetError) as e:
            print(f"第 {attempt} 次上传失败:{str(e)}")
            time.sleep(retry_delay)
            
            # 检查FTP连接是否存活,断开则重新登录
            try:
                ftp.voidcmd('NOOP')  # 发送空命令验证连接
            except ftplib.error_temp:
                print("FTP连接已断开,重新登录...")
                ftp.login(your_username, your_password)  # 替换为你的FTP账号密码
    
    print(f"经过 {max_retries} 次重试后,仍无法上传文件:{remote_filename}")
    return False

3. 整合到你的现有代码中

把原来的上传部分替换成这个重试函数即可:

# 检查文件完整性
with open(img_list[0][0], "rb") as oFile:
    check_chars = oFile.read()[-2:] 
if check_chars != b"\xff\xd9":
    print(f"文件不完整,跳过:{img_list[0][1]}")
    time.sleep(1)
    continue 

print("準備上傳: %s" % img_list[0][1])
# 调用带重试的上传函数
upload_with_retry(ftp, img_list[0][0], img_list[0][1], cut_switch)

额外优化建议

  • 增加日志记录:把上传的成功/失败信息写入日志文件,方便后续排查问题
  • 批量上传控制:如果是大量图片,不要一次性同时上传太多,避免触发服务器的并发限制
  • 服务器端文件检查:上传前可以用ftp.size(remote_filename)检查目标文件是否存在且大小正常,再决定是覆盖还是跳过

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.06 17:32:36