FTP 文件上传下载(Python实现)

FTP 服务器

1.功能
1.分为服务器和客户端两部分,要求启动服务端可以有多个客户端进行连接操作
2.客户端可以选择文件库中的文件进行下载
3.客户端可以上传本地文件到文件库

2.技术分析
1.TCP+多线程
2.判断普通文件:os.path.isfile()
3.查看文件列表:os.listdir()
4.os 模块方法实例:
os.path.isfile(’/home/tarena/a.py’)#判断是否为普通文件,返回布尔值
os.listdir(’/home/tarena/’)#列表形式显示所有文件和文件夹,每个文件就是列表中的元素

3.结构设计
1.将功能说明中 2 3 4 三个功能封装在一个类中

4.实现步骤
1.搭建网络
2.封装类
3.功能实现和测试

FTP 服务器项目实现:
1.搭建网络模型
2.搭建类(程序架构)
1.确定客户端发送请求和服务端回复的种类
3.文件列表功能实现
1.客户端
1.向服务端发送 L 开头的请求
2.等待接收服务端的反馈,服务端把文件名发送给客户端并打印
当接收到 ## 的时候,结束

ftpserver模块:

from socket import *
import sys
import os
from threading import Thread
import time

address = ('0.0.0.0',8888)
filedir = '/home/tarena/project/download/'

def doRequest(client):
    #创建对象,每个客户端都有一个单独的对象来处理功能
    serverobj = ftpserver(client)
    #接收客户端的请求
    while True:
        message = client.recv(1024).decode()
        msglist = message.split(' ')
        if msglist[0] == 'L':
            serverobj.dolist()
        if msglist[0] == 'G':
            serverobj.doget(msglist[-1])
        if msglist[0] == 'P':
            serverobj.doput(msglist[-1])
        elif msglist[0] == 'Q':
            serverobj.doexit()

class ftpserver(object):
    def __init__(self,client):
        self.client = client

    def dolist(self):
        
        filelist = os.listdir(filedir)
        if not filelist:
            self.client.send('文件库为空'.encode())
            
            time.sleep(0.1)
        else:
            self.client.send(b'OK')
            #发送文件名到客户端
            for file in filelist:
                #判断是否为普通文件
                if os.path.isfile(filedir+file) and file[0] != '.':
                    self.client.send(file.encode())
                    time.sleep(0.1)

            self.client.send(b'##')
            time.sleep(0.1)

    def doget(self,filename):
        try:
            f = open(filedir+filename,'rb')
        except:
            self.client.send('文件不存在'.encode())
            return
        
        #文件已正常打开
        self.client.send(b'OK')
        time.sleep(0.1)
        #发送文件的内容
        while True:
            data = f.read(1024)
            if not data:
                self.client.send(b'##')
                time.sleep(0.1)
                break
            self.client.send(data)
            #发送完毕后关闭文件
            f.close()

    def doput(self,filename):
        try:
            f = open(filedir+filename,'wb')
        except:
            self.client.send('上传失败'.encode())
            return
        self.client.send(b'OK')
        while True:
            data = self.client.recv(1024)
            if data == b'##':
                break
            f.write(data)
        f.close()

    def doexit(self):
        sys.exit(0)

def main():
    server = socket(AF_INET,SOCK_STREAM)
    server.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)
    server.bind(address)
    server.listen(10)
    print('正在等待客户端连接......')

    while True:
        try:
            client,addr = server.accept()
            print('客户端已连接:',addr)
        except KeyboardInterrupt:
            sys.exit("服务器已经断开!")
        except Exception as e:
            print(e)
            continue
        t = Thread(target=doRequest,args=(client,))
        t.setDaemon(True)
        t.start()
        
if __name__ == "__main__" :
    main()

ftpclient.py

from socket import *
import sys

class ftpclient(object):

    def   __init__(self,client):
        self.client = client

    def dolist(self):
        #向服务端发送请求,接收服务端消息
        self.client.send(b'L')
        data = self.client.recv(1024).decode()
        if data == 'OK':
            while True:
                filename = self.client.recv(1024).decode()
                if filename == '##':
                    break
                print('\033[32m'+filename+'\033[0m')
        else:
            print(data)

    def doget(self):
        filename = input('请输入要下载的文件名:')
        message = 'G ' + filename
        self.client.send(message.encode())
        data = self.client.recv(1024).decode()
        if data == 'OK':
            f = open(filename,'wb')
            while True:
                data = self.client.recv(1024)
                if data == b'##':
                    break
                f.write(data)
            f.close()
            print('%s 下载完成' % filename)
        else:
            print(data)
            

    def doput(self):
        filename = input('请输入要上传的文件:')
        filename2 = filename.split('/')[-1]
        try:
            f = open(filename,'rb')
        except:
            print('没有这个文件')
            return

        self.client.send(('P '+filename2).encode())
        data = self.client.recv(1024)
        if data == b'OK':
            while True:
                data = f.read(1024)
                if not data:
                    import time
                    time.sleep(0.1)
                    self.client.send(b'##')
                    break
                self.client.send(data)
            f.close()
            print('%s 上传完成' % filename2)

    def doexit(self):
        self.client.send(b'Q')
        sys.exit('谢谢使用')

def main():
    if len(sys.argv)<3:
        print('参数错误')
        return
    address = (sys.argv[1],int(sys.argv[2]))
    client = socket(AF_INET,SOCK_STREAM)
    try:
        client.connect(address)
    except Exception as e:
        print("服务器连接失败!",e)
        return
    while True:
        #创建对象,调用类内的方法
        clientobj = ftpclient(client)
        print("============我的网盘===========")
        print("***    1.查看文件列表       *****")
        print("***    2.下载文件       *****")
        print("***    3.上传文件       *****")
        print("***    4.退出网盘       *****")
        print("==============================")
        cmd = input('请做出选择(1/2/3/4')
        if cmd.strip() in ['1','2','3','4']:
            if cmd == '1':
                clientobj.dolist()
            elif cmd == '2':
                clientobj.doget()
            elif cmd == '3':
                clientobj.doput()
            else:
                clientobj.doexit()
        else:
            print('请做出正确的选择(1/2/3/4)')
        
if __name__ == "__main__":
    main()

你可能感兴趣的:(ubuntu,socket,python,网络编程,FTP)