1. 程式人生 > >老男孩Day8作業:FTP

老男孩Day8作業:FTP

bind 文件名 .py 客戶 txt pre 返回 獲取 有效

1、作業需求

開發簡單的FTP:

1. 用戶登陸

2. 上傳/下載文件

3. 不同用戶家目錄不同

4. 查看當前目錄下文件

5. 充分使用面向對象知識

2、流程圖

技術分享圖片

3、目錄結構

技術分享圖片

4、代碼區

bin目錄下的start.py程序執行文件

技術分享圖片
# -*- coding:utf-8 -*-
# Author:D.Gray
import os,sys
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.append(BASE_DIR)

from core import ftp_client
fc 
= ftp_client.FTP_client()
start_client.py 技術分享圖片
# -*- coding:utf-8 -*-
# Author:D.Gray
import os,sys
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.append(BASE_DIR)
from core import ftp_server
fs = ftp_server.FTP_server()
start_server.py

conf目下的setting.py系統配置文件

技術分享圖片
# -*- coding:utf-8 -*-
# Author:D.Gray import os,sys,socket BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) #IP地址和端口 IP_PORT = ("localhost",6969) #數據文件路徑 USER_FILE = BASE_DIR + r"\db\user.db" #用戶文件目錄 USER_HOME = BASE_DIR
setting.py

core目錄下主程序文件

技術分享圖片
# -*- coding:utf-8 -*-
# Author:D.Gray
import os,sys,socket
from conf import setting from core import ftp_server from core import users class FTP_client(object): def __init__(self): self.client = setting.socket.socket() self.client.connect(setting.IP_PORT) self.user_obj = users.Users() self.help_info = { "get":"用於上傳文件,例如:get readme.txt 即 get 文件名", "put":"用於下載文件,例如:put readme.txt 即 put 文件名", dir:"用於顯示當前目錄下文件或文件詳細信息 格式 ls " } if self.auth(): self.start() def auth(self): ‘‘‘ 用戶登錄驗證函數 :return: ‘‘‘ while True: username = input("請輸入用戶名>>>:").strip() pwd = input("請輸入用戶密碼>>>:").strip() auth_info = auth %s %s%(username,pwd) #格式化輸出 auth 用戶名 密碼 self.client.send(auth_info.encode()) #將格式化後的內容發送給服務端 back_res = self.client.recv(1024).decode() if back_res == "ok": print(認證成功) user = self.user_obj.get_user(username) self.current_user = username self.current_pwd = pwd self.current_path = user[home] self.current_dir = back_res[1] return True elif back_res == "Not password": print("\033[31;1m密碼不正確\033[0m") else: print("\033[31;1m用戶不存在\033[0m") def start(self): ‘‘‘ 輸入指令上傳下載文件函數 :return: ‘‘‘ while True: user_input = input(%s>>>:%self.current_user).strip() if len(user_input) == 0:continue user_input = user_input.split() if user_input[0] == q:break if hasattr(self,user_input[0]): func = getattr(self,user_input[0]) func(user_input) else: print("\033[31;1m請輸入有效指令\033[0m") continue def put(self,cmd): ‘‘‘ 從服務器端下載文件函數 :param cmd: :return: ‘‘‘ print(in the put:,cmd) send_server_info = %s %s%(cmd[0],cmd[1]) #格式化輸出[‘方法‘,‘文件名‘] self.client.send(send_server_info.encode()) #將格式化輸出內容發送給服務器端 server_back = self.client.recv(1024).decode() #接收服務器回調結果 print("接收服務器回調信息:",server_back) if server_back == "302": print(\033[31;1m文件不存在\033[0m) else: file_totle_size = int(server_back) #從服務器端接收文件大小 print("您要下載的文件大小為:%sByte"%file_totle_size) self.client.send(可以開始下載了....encode()) rever_file_size = 0 #接收到的文件大小 file_name_path = setting.USER_HOME + self.current_path + \\user_home\\ + cmd[1] #print(file_name_path) with open(file_name_path,"wb") as f: while rever_file_size < file_totle_size: if file_totle_size - rever_file_size < 1024: #當剩余文件大小<1024 全部接收文件 size = file_totle_size - rever_file_size else: size = 1024 data = self.client.recv(size) #當剩余文件<1024全部接收文件,當剩余文件>1024每次只接收1024 rever_file_size += len(data) #每次接收數據時自動累計rever_file_size值 print("已接收%sByte"%rever_file_size) f.write(data) else: print(接受完畢) def get(self,cmd): ‘‘‘ 本地上次文件給服務器端 :param cmd: 接收用戶通過start函數輸入的操作指令 :return: ‘‘‘ print(cmd) file_path = setting.USER_HOME + self.current_path +\\user_home\\ + cmd[1] if os.path.isfile(file_path): file_totle_size = os.stat(file_path).st_size print(您要上傳文件大小為【%sByte】%file_totle_size) file_info = %s %s %s%(cmd[0],cmd[1],file_totle_size) #格式化輸出[‘操作指令‘,‘文件名‘,‘文件大小‘] self.client.send(file_info.encode()) #將格式化輸出內容發送給服務器端 server_back = self.client.recv(1024).decode() #接收回調信息 if server_back == "300": print(可以上傳文件了...) send_file_size = 0 with open(file_path,rb) as f: while send_file_size != file_totle_size: if file_totle_size-send_file_size <= 1024: data = f.read(file_totle_size-send_file_size) send_file_size += file_totle_size - send_file_size else: data = f.read(1024) send_file_size += len(data) print("已上傳【%sByte】"%send_file_size) self.client.send(data) print("上傳成功") else: print(\033[31;1m文件不存在\033[0m) def dir(self,cmd): ‘‘‘ 查看服務端目錄文件信息 :param cmd: :return: ‘‘‘ print(cmd) send_server_info = %s%cmd[0] #格式化輸出用戶指令 self.client.send(send_server_info.encode()) server_back = self.client.recv(1024).decode() #接收服務端回調 print("獲取服務端回調信息:%s"%server_back) self.client.send("ok".encode()) #發送給服務端‘ok‘ recv_size = 0 recv_data = b‘‘ while recv_size < int(server_back): data = self.client.recv(1024) recv_data += data recv_size = len(data) print(recv_size) else: print(recv_data.decode()) def help(self,cmd): ‘‘‘ 查看幫助文檔函數 :param cmd: :return: ‘‘‘ print(cmd) d = self.help_info print(d)
ftp_client.py 技術分享圖片
# -*- coding:utf-8 -*-
# Author:D.Gray
import os,sys,socket
from conf import setting
from core import ftp_client
from core import users

class FTP_server(object):
    def __init__(self):
        self.server = setting.socket.socket()
        self.server.bind(setting.IP_PORT)
        self.server.listen(5)
        self.user_obj = users.Users()  #導入users文件並實例化Users類
        self.start()

    def start(self):
        print("等待鏈接中...")
        while True:
            self.conn,self.addr = self.server.accept()
            print("一個新的鏈接:%s %s"%(self.conn,self.addr))
            while True:
                self.data = self.conn.recv(1024)  #接受客戶端格式化輸出內容
                #print(‘data:‘,self.conn)
                if not self.data:
                    print("客戶端斷開")
                    break
                cmd_res = self.data.decode().split() #以列表形式獲取用戶輸入的[[方法名],[文件名]]
                cmd_action = cmd_res[0]     #獲取方法名
                #print(‘in the start獲取方法名:‘,cmd_action)
                if hasattr(self,cmd_action):    #判斷用戶輸入的方法名是否存在
                    func = getattr(self,cmd_action) #執行對應的方法函數
                    func(cmd_res)   #用戶輸入的[[方法名],[文件名]]傳給方法函數
                else:
                    print("\033[31;1m請輸入有效命令\033[0m")

    def auth(self,cmd):
        #print(‘auth:‘,cmd) #接受客戶端格式化輸出的 auth 用戶名 密碼
        user = self.user_obj.get_user(cmd[1])   #調用Users類中get_user方法,並把cmd[1](用戶名)傳參給get_user方法
        print(in the ftp_server_auth:,user)
        if user:
            if user[password] == cmd[2]:
                self.current_user = user
                self.current_path = user["home"]
                self.user_home = setting.USER_HOME
                self.conn.send(b"ok")
            else:
                self.conn.send(b"Not password")
        else:
            self.conn.send(bNot username)

    def put(self,cmd):
        ‘‘‘
        上傳文件函數
        :param cmd: 接收用戶輸入的[[方法名],[文件名]]
        :return:
        ‘‘‘
        #print(‘in the put:‘,cmd)
        file_name_path = self.user_home + self.current_path +\server_home\\+ cmd[1]
        print(文件路徑,file_name_path)
        if os.path.isfile(file_name_path):
            file_totle_size = os.stat(file_name_path).st_size #查看文件大小
            self.conn.send(str(file_totle_size).encode())   #將文件大小發送給客戶端
            self.conn.recv(1024)    #接收客戶端消息
            with open(file_name_path,rb) as f:
                for line in f:      #循環遍歷文件內容
                    self.conn.send(line)    #並將文件內容發送給客戶端
            print("send done>>>")
        else:
            print(\033[31;1m文件不存在\033[0m)
            self.conn.send(302.encode())

    def get(self,cmd):
        ‘‘‘
        接收客戶端上傳文件函數
        :param cmd:
        :return:
        ‘‘‘
        print(cmd)
        file_path = self.user_home + self.current_path + \server_home\\ + cmd[1]  #文件路徑
        file_totle_size = cmd[2]    #接收客戶端上傳文件大小
        file_totle_size = int(file_totle_size)
        with open(file_path,wb) as f:
            self.conn.send(300.encode())  #返回客戶端參數300
            revered_file_size = 0   #初始接收文件大小
            while revered_file_size < file_totle_size:  #開始接收客戶端上傳文件
                if file_totle_size - revered_file_size <= 1024:
                    size = file_totle_size-revered_file_size
                else:
                    size = 1024
                data = self.conn.recv(size)
                revered_file_size += len(data)
                f.write(data)
            else:
                print("文件接收完畢")

    def dir(self,cmd):
        ‘‘‘
        查看服務端目錄文件信息函數
        :param cmd:
        :return:
        ‘‘‘
        print(cmd)
        file_path = self.user_home + self.current_path + \server_home\\
        res = os.popen(%s %s%(cmd[0],file_path)).read()
        print(服務端文件目錄信息:,res)
        if len(res) == 0 :
            res = cmd has not output
        self.conn.send(str(len(res)).encode()) #服務端發送目錄文件大小給客戶端
        self.conn.recv(1024)    #接收客戶端回調信息 "ok"
        self.conn.send(res.encode()) #服務端發送目錄文件信息給客戶端
ftp_server.py

db目錄下的數據文件

技術分享圖片
[
    {
        "username":"alex",
        "password":"admin",
        "home":"\\home\\alex\\",
    }
]
user.db

老男孩Day8作業:FTP