ftplib 应用

背景

这是一个奇怪而少见的场景:我工作在 A 网络中,需要 B 网络中的 Server 给我提共服务(编译中的一个步骤),但是 A 和 B 是不可以相互连接的。而 A 和 B 网络现有的可用工具只有 ftp。所以常规的流程就是:

  1. 在 A 网络中生成所需文件;
  2. 将其通过 ftp 发送至一个中转网络的电脑上;
  3. 中转电脑(C网络中)将文件通过 ftp 发送到 B 网络的电脑上;
  4. B 网络中的电脑,处理完,将生成的文件通过 ftp 发送到中转电脑;
  5. 中转电脑将文件通过 ftp 发送到 A 网络的电脑上;

设计

实际应用中非常浪费时间,并且浪费人力。所以就想到用 ftplib 来自动化处理这些事务。设计如下:

Code

A 网络端

import hashlib
import os
import sys
import ftplib
import configparser
import time

config = configparser.ConfigParser()
config.read('local.ini')
ftp_work_dir = config['dir']['ftp']
ip = config['net']['ip']
username = config['net']['username']
password = config['net']['password']

def file_hash(file_path: str, hash_method) -> str:
    if not os.path.isfile(file_path):
        print('文件不存在。')
        return ''
    h = hash_method()
    with open(file_path, 'rb') as f:
        while b := f.read(8192):
            h.update(b)
    return h.hexdigest()

def file_sha256(file_path: str) -> str:
    return file_hash(file_path, hashlib.sha256)

def download_file(ftp, remote_file, localfile):
    with open(localfile, 'wb') as fp:
        print(ftp.retrbinary('RETR ' + remote_file, fp.write))
    fp.close() 

def uploadfile(ftp, remoteFile, localFile):
    with open(localFile, 'rb') as fp:
        print(ftp.storbinary('STOR ' + remoteFile, fp, 1024))
    fp.close() 

if __name__ == "__main__":
    ftp = ftplib.FTP_TLS()
    print(ftp.connect(ip, 21))
    print(ftp.login(username, password))
    print(ftp.prot_p())
    print(ftp.cwd(ftp_work_dir))

    if len(sys.argv) == 2:
        codesign_file = sys.argv[1]
        flag_file = file_sha256(codesign_file)
        os.system('echo ' + codesign_file + '___' + flag_file[0:8] + '>' + flag_file[0:8])
        uploadfile(ftp, 'codesign/' + codesign_file + '___' + flag_file[0:8], codesign_file)
        uploadfile(ftp, 'flag/' + flag_file[0:8], flag_file[0:8])

        print('please wait ......')
        while not 'done__' + flag_file[0:8] in ftp.nlst('./'):
            time.sleep(2)
        bin_zip = 'ABC_bin___' + codesign_file.split('.7z')[0] + '__' + flag_file[0:8] + '.zip'
        download_file(ftp, 'bin/' + bin_zip, bin_zip)
        ftp.delete('bin/' + bin_zip)
        ftp.delete('done__' + flag_file[0:8])
        os.remove(flag_file[0:8])        
    else: 
        print('argument error!')

    ftp.close()

有个配置文件,如此程序的通用性更好:

[dir]
ftp=ftp_work_dir

[net]
ip=ftp_ip
username=ftp_username
password=ftp_password

中转端

import os
import ftplib
import time
import configparser

codesign_hash = ''

config = configparser.ConfigParser()
config.read('transfer.ini')
ftp_work_dir = config['dir']['ftp']
A_ip = config['A_net']['ip']
A_username = config['A_net']['username']
A_password = config['A_net']['password']
B_ip = config['B_net']['ip']
B_username = config['B_net']['username']
B_password = config['B_net']['password']

def download_file(ftp, remote_file, localfile):
    with open(localfile, 'wb') as fp:
        print(ftp.retrbinary('RETR ' + remote_file, fp.write))
    fp.close() 

def uploadfile(ftp, remoteFile, localFile):
    with open(localFile, 'rb') as fp:
        print(ftp.storbinary('STOR ' + remoteFile, fp, 1024))
    fp.close() 

def monitor_A_ftp(A_ftp, B_ftp):
    global codesign_hash
    res = None
    codesigns_flag = A_ftp.nlst('flag')
    while len(codesigns_flag) == 0:
        codesigns_flag = A_ftp.nlst('flag')
        time.sleep(2)
    flag = codesigns_flag[0].split('/')[1]
    download_file(A_ftp, codesigns_flag[0], flag)
    with open(flag, 'r') as f:
        res = f.readline().split('\n')[0]  # res means codesign files
        print(res)
    if res != None:
        codesign_hash = 'done__' + res.split('___')[1]
        download_file(A_ftp, 'codesign/' + res, res)
        uploadfile(B_ftp, 'codesign/' + res, res)
        uploadfile(B_ftp, codesigns_flag[0], flag)
        A_ftp.delete('codesign/' + res)
        A_ftp.delete(codesigns_flag[0])
        os.remove(res)
        os.remove(flag)

def monitor_B_ftp(A_ftp, B_ftp):
    global codesign_hash
    print('please wait ......')
    while not codesign_hash in B_ftp.nlst('./'):
        time.sleep(2)
    abc_bin = B_ftp.nlst('bin')[0]
    local_bin = abc_bin.split('/')[1]
    download_file(B_ftp, codesign_hash, codesign_hash)
    download_file(B_ftp, abc_bin, local_bin)
    uploadfile(A_ftp, abc_bin, local_bin)
    uploadfile(A_ftp, codesign_hash, codesign_hash)
    B_ftp.delete(abc_bin)
    B_ftp.delete(codesign_hash)
    os.remove(local_bin)
    os.remove(codesign_hash)

def while_monitor(A_ftp, B_ftp):
    while True:
        monitor_A_ftp(A_ftp, B_ftp)
        monitor_B_ftp(A_ftp, B_ftp)

if __name__ == "__main__":
    A_ftp = ftplib.FTP_TLS()
    print(A_ftp.connect(A_ip, 21))
    print(A_ftp.login(A_username, A_password))
    print(A_ftp.prot_p())
    print(A_ftp.cwd(ftp_work_dir))
    
    B_ftp = ftplib.FTP_TLS()
    print(B_ftp.connect(B_ip, 21))
    print(B_ftp.login(B_username, B_password))
    print(B_ftp.prot_p())
    print(B_ftp.cwd(ftp_work_dir))

    while_monitor(A_ftp, B_ftp)

    A_ftp.close()
    B_ftp.close()

同样有个配置文件:

[dir]
ftp=ftp_work_dir

[A_net]
ip=ftp_ip
username=ftp_username
password=ftp_password

[B_net]
ip=ftp_ip
username=ftp_username
password=ftp_password

B 网络端

import sys
import os
import ftplib
import time
import subprocess
import shutil
import configparser

config = configparser.ConfigParser()
config.read('remote.ini')
ftp_work_dir = config['dir']['ftp']
ip = config['net']['ip']
username = config['net']['username']
password = config['net']['password']

def download_file(ftp, remote_file, localfile):
    with open(localfile, 'wb') as fp:
        print(ftp.retrbinary('RETR ' + remote_file, fp.write))
    fp.close() 

def uploadfile(ftp, remoteFile, localFile):
    with open(localFile, 'rb') as fp:
        print(ftp.storbinary('STOR ' + remoteFile, fp, 1024))
    fp.close() 

def run_codesign(codesign_dir):
    shutil.copyfile('001_run.bat', codesign_dir + '/001_run.bat')
    shutil.copyfile('002_move.bat', codesign_dir + '/002_move.bat')
    os.remove(codesign_dir + '/CodeSign.exe')
    os.remove(codesign_dir + '/CodeSign_Account.bat')
    shutil.copyfile('CodeSign.exe', codesign_dir + '/CodeSign.exe')
    shutil.copyfile('CodeSign_Account.bat', codesign_dir + '/CodeSign_Account.bat')
    p = subprocess.Popen('cmd.exe /c 001_run.bat', cwd=codesign_dir)
    stdout, stderr = p.communicate()
    print(p.returncode)
    p = subprocess.Popen('cmd.exe /c 002_move.bat', cwd=codesign_dir)
    stdout, stderr = p.communicate()
    print(p.returncode)

def monitor_tw_ftp(tw_ftp):
    res = None
    codesigns_flag = tw_ftp.nlst('flag')
    print(codesigns_flag)
    if len(codesigns_flag) != 0:
        flag = codesigns_flag[0].split('/')[1]
        download_file(tw_ftp, codesigns_flag[0], flag)
        with open(flag, 'r') as f:
            res = f.readline().split('\n')[0]
            print(res)
        if res != None:
            download_file(tw_ftp, 'codesign/' + res, res)
            codesign_dir = res.split('___')[0].split('.7z')[0]
            cmd = '"C:/Program Files/7-Zip/7z.exe" x ' + res + ' ' + codesign_dir
            os.system(cmd)
            bin_zip = 'ABC_bin___' + codesign_dir + '__' + res.split('___')[1] + '.zip'
            if os.path.exists(codesign_dir + '/a_all.bin'):
                run_codesign(codesign_dir)
                cmd = '"C:/Program Files/7-Zip/7z.exe" a ' + bin_zip + ' ' + codesign_dir + '/ABC_bin'
                os.system(cmd)
            else:
                subdir = os.listdir(codesign_dir)[0]
                run_codesign(codesign_dir + '/' + subdir)
                cmd = '"C:/Program Files/7-Zip/7z.exe" a ' + bin_zip + ' ' + codesign_dir + '/' + subdir + '/ABC_bin'
                os.system(cmd)
            uploadfile(tw_ftp, 'bin/' + bin_zip, bin_zip)
            os.system('echo done > done__' + res.split('___')[1])
            uploadfile(tw_ftp, 'done__' + res.split('___')[1], 'done__' + res.split('___')[1])
            tw_ftp.delete('codesign/' + res)
            tw_ftp.delete(codesigns_flag[0])
            # os.removedirs(codesign_dir)
            shutil.rmtree(codesign_dir, ignore_errors=True)
            os.remove(bin_zip)
            os.remove('done__' + res.split('___')[1])
            os.remove(flag)
            os.remove(res)

if __name__ == "__main__":
    ftp = ftplib.FTP_TLS()
    print(ftp.connect(ip, 21))
    print(ftp.login(username, password))
    print(ftp.prot_p())
    print(ftp.cwd(ftp_work_dir))

    while True:
        monitor_tw_ftp(ftp)
        time.sleep(2)

配置文件如下:

[dir]
ftp=ftp_work_dir

[net]
ip=ftp_ip
username=ftp_username
password=ftp_password

使用

完成后,work_dir 下便有了一个 zip 文件(包含结果文件)。

PS C:\work_dir> py .\local.py SourceFile.7z
220 Welcome to Phison FTP2
230 使用者 Hosinglobal 登入
200 Protection set to Private
250 CWD 命令成功執行
226 傳送完畢
226 傳送完畢
please wait ......
226 傳送完畢
PS C:\work_dir>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
FTP Library Routines Release 4.0 Thomas Pfau (tfpfau@gmail.com) June 7, 2013 This package implements a callable interface to FTP. The FTP protocol is specified in RFC 959. The library has been tested on linux, OpenVMS and Windows NT. It should also work without major modification on other POSIX systems. All programs using the library should include ftplib.h. FTP开源库。 Miscellaneous Functions FtpInit() - Initialize the library FtpSite() - Send a 'SITE' command FtpLastResponse() - Retrieve last server response FtpSysType() - Determine remote system type FtpSize() - Determine size of remote file FtpSizeLong() - Determine size of remote file FtpModDate() - Determine modification time of file FtpSetCallback() - Establish a callback function FtpClearCallback() - Remove a callback function Server Connection FtpConnect() - Connect to a remote server FtpLogin() - Login to remote machine FtpQuit() - Disconnect from remote server FtpOptions() - Set Connection Options Directory Functions FtpChdir() - Change working directory FtpMkdir() - Create a directory FtpRmdir() - Remove a directory FtpDir() - List a remote directory FtpNlst() - List a remote directory FtpCDUp() - Change to parent directory FtpPwd() - Determine current working directory File to File Transfer FtpGet() - Retreive a remote file FtpPut() - Send a local file to remote FtpDelete() - Delete a remote file FtpRename() - Rename a remote file File to Program Transfer These routines allow programs access to the data streams connected to remote files and directories. FtpAccess() - Open a remote file or directory FtpRead() - Read from remote file or directory FtpWrite() - Write to remote file FtpClose() - Close data connection Utilities qftp - Command line ftp utility
你可以使用PyQt5和ftplib库来创建一个FTP客户端应用程序。以下是一个简单的示例代码,可以连接到Linux上的FTP服务器并提供上传和下载文件的功能: ```python import sys from PyQt5.QtWidgets import QApplication, QMainWindow, QLabel, QPushButton, QFileDialog from PyQt5.QtCore import Qt from ftplib import FTP class FTPClient(QMainWindow): def __init__(self): super().__init__() self.initUI() def initUI(self): self.setWindowTitle("FTP Client") self.setGeometry(100, 100, 300, 200) self.lbl_status = QLabel(self) self.lbl_status.setAlignment(Qt.AlignCenter) self.lbl_status.setGeometry(10, 10, 280, 30) self.btn_upload = QPushButton("Upload", self) self.btn_upload.setGeometry(10, 50, 130, 30) self.btn_upload.clicked.connect(self.uploadFile) self.btn_download = QPushButton("Download", self) self.btn_download.setGeometry(150, 50, 130, 30) self.btn_download.clicked.connect(self.downloadFile) self.show() def uploadFile(self): file_path, _ = QFileDialog.getOpenFileName(self, "Select File to Upload") if file_path: ftp = FTP('ftp.example.com') ftp.login('username', 'password') with open(file_path, 'rb') as file: ftp.storbinary('STOR ' + file_path.split('/')[-1], file) ftp.quit() self.lbl_status.setText("File uploaded successfully") def downloadFile(self): file_path, _ = QFileDialog.getSaveFileName(self, "Save File") if file_path: ftp = FTP('ftp.example.com') ftp.login('username', 'password') with open(file_path, 'wb') as file: ftp.retrbinary('RETR ' + file_path.split('/')[-1], file.write) ftp.quit() self.lbl_status.setText("File downloaded successfully") if __name__ == '__main__': app = QApplication(sys.argv) window = FTPClient() sys.exit(app.exec_()) ``` 在代码中,你需要将`ftp.example.com`替换为你的FTP服务器的地址,`username`和`password`替换为你的登录凭据。上传和下载文件的功能分别在`uploadFile`和`downloadFile`方法中实现。 注意:这只是一个简单的示例,你可能需要添加错误处理和其他功能来完善你的FTP客户端应用程序。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值