import paramiko
import sys
import os

def print_progress(transferred, total):
    progress = transferred / total * 100
    sys.stdout.write(f"\r传输进度：{progress:.2f}% ({transferred}/{total} 字节)")
    sys.stdout.flush()

def sftp_upload(local_path, remote_path, host, port, username, password):
    try:
        # 创建一个SSH客户端对象
        ssh_client = paramiko.SSHClient()
        # 自动添加主机密钥
        ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
        # 连接到SFTP服务器
        ssh_client.connect(hostname=host, port=port, username=username, password=password)
        # 创建一个SFTP客户端对象
        sftp_client = ssh_client.open_sftp()

        # 检查远程文件是否存在，如果不存在，则创建路径中的目录和文件
        try:
            sftp_client.stat(remote_path)
            print(f"远程文件 {remote_path} 已存在")
        except FileNotFoundError:
            # 获取远程路径中的目录部分
            remote_dir = os.path.dirname(remote_path)
            # 创建远程目录
            if remote_dir:
                try:
                    sftp_client.stat(remote_dir)
                except FileNotFoundError:
                    sftp_client.mkdir(remote_dir)
                    print(f"已在远程服务器上创建目录 {remote_dir}")
            # 创建远程文件
            sftp_client.open(remote_path, 'w').close()
            print(f"已在远程服务器上创建文件 {remote_path}")

        # 上传文件，并传入回调函数来显示传输进度
        sftp_client.put(local_path, remote_path, callback=print_progress)
        # 输出换行符，以便下一行正常显示
        print()
        print(f"文件成功上传")

        # 关闭SFTP连接
        sftp_client.close()
        # 关闭SSH连接
        ssh_client.close()
    except Exception as e:
        print(f"上传文件时发生错误: {e}")
        # 打印异常类型
        print(f"异常类型: {type(e)}")
        # 打印异常消息
        print(f"异常消息: {e}")
        # 打印异常的堆栈跟踪信息
        import traceback
        traceback.print_exc()

if __name__ == "__main__":
    # 从命令行参数中获取本地文件路径、远程文件路径以及SFTP服务器相关信息
    if len(sys.argv) < 7:
        print("用法: python script.py <本地文件路径> <远程文件路径> <SFTP服务器地址> <端口> <用户名> <密码>")
        sys.exit(1)

    local_path = sys.argv[1]
    remote_path = sys.argv[2]
    host = sys.argv[3]
    port = int(sys.argv[4])
    username = sys.argv[5]
    password = sys.argv[6]
    # 检查本地文件是否存在
    if not os.path.exists(local_path):
        print(f"本地文件 {local_path} 不存在")
        sys.exit(1)
    # 上传文件到SFTP服务器
    sftp_upload(local_path, remote_path, host, port, username, password)