immersed-in-the-deep-sea

导航

 

对比如下:

特性维度FTPSFTPSCPTFTP
安全性 明文传输 基于SSH加密 基于SSH加密 无加密
默认端口 21 22 22 69
协议基础 TCP SSH SSH UDP
认证方式 用户名/密码 多种(如公钥) SSH认证 无认证
交互性 交互式命令 交互式命令 仅命令行 非交互式
目录操作 支持 支持 -r递归 不支持
适用场景 内网、匿名访问 安全要求高的环境 简单文件复制 局域网内小文件、网络设备配置

 

ftp ip地址

输入用户名密码进入以后。

dir查看当前目录

put 可以put本地内容进当前目录

比如 put D:/1.txt 远程文件名

get 远程文件名 本地文件名

delete删除

这是当时已经成功实现功能的代码,具体的嘛,懒得讲了和说了,就是上传文件还有每进度5%给出日志提示

def vm_upload(**kwargs):
    step_progress_callback = kwargs.get('step_progress_callback')
    host = kwargs.get("IP")
    username = kwargs.get("LoginName")
    pwd = kwargs.get("LoginPwd")

    # 实例化 FTP
    ftp = FTP()

    # 设置调试等级, 0 不调试, 1 只打印命令与响应, 2 打印详细信息
    ftp.set_debuglevel(0)

    # 设置 FTP 主动被动模式, False 主动模式, True 被动模式(默认的模式)
    ftp.set_pasv(True)

    # 设置编码格式
    ftp.encoding = 'utf-8'

    try:
        # 连接与登录
        ftp.connect(host, 21)
        ftp.login(username, pwd)
        logger.info(f"FTP connection successful: {ftp.getwelcome()}")

        step_progress_callback(20)

        # 切换到目标目录
        ftp.cwd("/oas/images")
        logger.info("Switched to directory: /oas/images")

        # 检测是否已有虚拟机文件,有则跳过上传
        remote_filename = VM_VMX
        local_file_to_upload = 'D:/'+VM_VMX

        try:
            # 尝试获取远程文件大小,如果文件存在则跳过上传
            remote_file_size = ftp.size(remote_filename)
            logger.info(f"Remote file already exists, size: {remote_file_size} bytes. Skipping upload.")

            # 可选:比较文件大小,如果不同则覆盖上传
            local_file_size = os.path.getsize(local_file_to_upload)
            if remote_file_size == local_file_size:
                logger.info("Local and remote file sizes match, skipping upload.")
                step_progress_callback(100)
                return True, "File already exists and sizes match, upload skipped"
            else:
                logger.info("File sizes differ, proceeding with upload...")
                # 删除远程文件以便重新上传
                ftp.delete(remote_filename)
                logger.info("Deleted existing remote file for re-upload")
        except error_perm as e:
            # 文件不存在,继续上传
            if "550" in str(e):
                logger.info("Remote file does not exist, proceeding with upload")
            else:
                raise e

        # 获取文件大小用于进度计算
        file_size = os.path.getsize(local_file_to_upload)
        logger.info(f"Starting file upload, size: {file_size} bytes ({file_size / 1024 / 1024:.2f} MB)")

        # 进度跟踪变量
        uploaded_size = 0
        last_logged_progress = 0

        def progress_callback(data):
            nonlocal uploaded_size, last_logged_progress
            uploaded_size += len(data)
            progress_percent = (uploaded_size / file_size) * 100

            # 每完成5%记录一次日志,避免过于频繁的日志输出
            if progress_percent - last_logged_progress >= 5 or uploaded_size == file_size:
                logger.info(f"Upload progress: {progress_percent:.1f}% ({uploaded_size}/{file_size} bytes)")
                last_logged_progress = progress_percent - (progress_percent % 5)

                # 更新步骤进度,从20%到100%
                step_progress = 20 + (progress_percent * 0.8)
                step_progress_callback(step_progress)

        # 上传文件(带进度回调)
        with open(local_file_to_upload, 'rb') as local_file:
            ftp.storbinary(f'STOR {remote_filename}', local_file, callback=progress_callback)

        logger.info("File upload completed")

        # 退出客户端
        ftp.quit()
        step_progress_callback(100)

        return True, "upload vm successfully"

    except Exception as e:
        logger.error(f"File upload failed: {str(e)}")
        # 确保在异常情况下也关闭连接
        try:
            if ftp:
                ftp.quit()
        except:
            pass
        return False, f"upload vm failed: {str(e)}"

 

posted on 2025-11-18 19:46  沉浸深海  阅读(0)  评论(0)    收藏  举报