python搭建FTP

1、FTP服務的主動模式和被動模式:

主動模式工作過程:
  1. 客戶端以隨機非特權(quán)端口N凌蔬,就是大于1024的端口露懒,對server端21端口發(fā)起連接
  2. 客戶端開始監(jiān)聽 N+1端口;
  3. 服務端會主動以20端口連接到客戶端的N+1端口砂心。
主動模式的優(yōu)點:

服務端配置簡單懈词,利于服務器安全管理,服務器只需要開放21端口

主動模式的缺點:

如果客戶端開啟了防火墻辩诞,或客戶端處于內(nèi)網(wǎng)(NAT網(wǎng)關之后)坎弯, 那么服務器對客戶端端口發(fā)起的連接可能會失敗
被動模式:

被動模式工作過程:
  1. 客戶端以隨機非特權(quán)端口連接服務端的21端口
  2. 服務端開啟一個非特權(quán)端口為被動端口,并返回給客戶端
  3. 客戶端以非特權(quán)端口+1的端口主動連接服務端的被動端口
被動模式缺點:

服務器配置管理稍顯復雜译暂,不利于安全抠忘,服務器需要開放隨機高位端口以便客戶端可以連接,因此大多數(shù)FTP服務軟件都可以手動配置被動端口的范圍

被動模式的優(yōu)點:

對客戶端網(wǎng)絡環(huán)境沒有要求

2外永、搭建客戶端通過【主動模式】連接服務器

服務器端配置(以下配置默認為有公網(wǎng)ip的服務器):
①安全組入方向映射:TCP/21端口
開別的端口會出現(xiàn):ftplib.error_perm: 501 Rejected data connection to foreign address xxx.
②安全組出方向打開允許TCP所有端口
③pip3 install pyftpdlib

主動模式下崎脉,服務器端代碼
from pyftpdlib.authorizers import DummyAuthorizer
from pyftpdlib.handlers import FTPHandler
from pyftpdlib.servers import FTPServer


# filepath = r"F:\videos"
filepath = "/root/workspace/zys/ftpfiles"

# 新建一個用戶組
authorizer = DummyAuthorizer()
# 將用戶名,密碼伯顶,指定目錄囚灼,權(quán)限 添加到里面
authorizer.add_user("xxx", "xxx", filepath, perm="elradfmwM")
# 這個是添加匿名用戶,任何人都可以訪問,如果去掉的話祭衩,需要輸入用戶名和密碼灶体,可以自己嘗試
# authorizer.add_anonymous(filepath)

handler = FTPHandler
handler.authorizer = authorizer

# 開啟服務器
port = 21
server = FTPServer(("0.0.0.0", port), handler)
server.serve_forever()


# 讀取權(quán)限
# "e" ——更改目錄(CWD,CDUP命令)
# "l" ——列表文件(LIST掐暮,NLST蝎抽,STAT,MLSD路克,MLST织中,SIZE命令)
# "r" ——從服務器檢索文件(RETR命令)
# 寫入權(quán)限
# "a" ——將數(shù)據(jù)追加到現(xiàn)有文件(APPE命令)
# "d" ——刪除文件或目錄(DELE锥涕,RMD命令)
# "f" ——重命名文件或目錄(RNFR,RNTO命令)
# "m" ——創(chuàng)建目錄(MKD命令)
# "w" ——將文件存儲到服務器(STOR狭吼,STOU命令)
# "M"——更改文件模式/權(quán)限(SITE CHMOD命令)
# "T"——更改文件修改時間(SITE MFMT命令)

主動模式下层坠,客戶端代碼(被動模式加了try-catch,可以參考)
from ftplib import FTP
import datetime
def ftpconnect(host, port, username, password):
    ftp = FTP()
    ftp.set_debuglevel(2)
    ftp.connect(host, port)
    ftp.login(username, password)
    ftp.set_pasv(False) ########################主動模式
    print(ftp.getwelcome())
    return ftp

def downloadfile(ftp, remotepath, localpath):
    # 從ftp下載文件
    bufsize = 1024
    fp = open(localpath, 'wb')
    ftp.retrbinary('RETR ' + remotepath, fp.write, bufsize)
    ftp.set_debuglevel(0)
    fp.close()


def uploadfile(ftp, localpath, remotepath):
    # 從本地上傳文件到ftp
    bufsize = 1024
    fp = open(localpath, 'rb')
    ftp.storbinary('STOR ' + remotepath, fp, bufsize)
    ftp.set_debuglevel(0)
    fp.close()

if __name__ == "__main__":
    ip = "xxxxxxx"
    ftp = ftpconnect(ip, 21, "xxx", "xxx")

    local_file = r'F:\videos\2023-02-04_01-58-09.mp4'
    for i in range(2):
        target_file = str(i) + 'xx.mp4'
        uploadfile(ftp, local_file, target_file)
    # downloadfile(ftp, "VID_20210830_103249.mp4", "11.mp4")
    ftp.quit()

3刁笙、搭建客戶端通過【被動模式】連接服務器

服務器端配置(以下配置默認為有公網(wǎng)ip的服務器):
①安全組-入方向映射:TCP/21端口破花,和passive_ports設定的主動模式下端口范圍
②安全組出方向不用設置
③pip3 install pyftpdlib

被動模式下,服務器端代碼
from pyftpdlib.authorizers import DummyAuthorizer
from pyftpdlib.handlers import FTPHandler
from pyftpdlib.servers import FTPServer


# filepath = r"F:\videos"
filepath = "/root/workspace/zys/ftpfiles"


# 新建一個用戶組
authorizer = DummyAuthorizer()
# 將用戶名疲吸,密碼座每,指定目錄,權(quán)限 添加到里面
authorizer.add_user("xxx", "xxx", filepath, perm="elradfmwM")
# 這個是添加匿名用戶,任何人都可以訪問摘悴,如果去掉的話峭梳,需要輸入用戶名和密碼,可以自己嘗試
# authorizer.add_anonymous(filepath)

handler = FTPHandler
handler.authorizer = authorizer
# 

#*******************添加被動端口范圍, client主動模式下蹂喻,不需要設置********************************
handler.passive_ports = range(38300, 38301)
#***********************************************************************

# 開啟服務器
port = 21
server = FTPServer(("0.0.0.0", port), handler)
server.serve_forever()


# 讀取權(quán)限
# "e" ——更改目錄(CWD葱椭,CDUP命令)
# "l" ——列表文件(LIST,NLST口四,STAT孵运,MLSD,MLST蔓彩,SIZE命令)
# "r" ——從服務器檢索文件(RETR命令)
# 寫入權(quán)限
# "a" ——將數(shù)據(jù)追加到現(xiàn)有文件(APPE命令)
# "d" ——刪除文件或目錄(DELE治笨,RMD命令)
# "f" ——重命名文件或目錄(RNFR,RNTO命令)
# "m" ——創(chuàng)建目錄(MKD命令)
# "w" ——將文件存儲到服務器(STOR赤嚼,STOU命令)
# "M"——更改文件模式/權(quán)限(SITE CHMOD命令)
# "T"——更改文件修改時間(SITE MFMT命令)

被動模式下旷赖,客戶端代碼(重寫makepasv方法)
from ftplib import FTP
import datetime


# 重寫makepasv方法, *************非常重要***************
# 作用是為了數(shù)據(jù)傳輸時使用服務器被動模式下返回的ip和port
# 防止出現(xiàn)卡在:*resp* '227 Entering passive mode (192,168,1,1x,xx,xxx).'
class MyFtp(FTP):
    def makepasv(self):
        host, port = super(MyFtp, self).makepasv()
        host = self.sock.getpeername()[0]
        print(host, port)
        return host, port


def ftpconnect(host, port, username, password):
    connectStatus = True
    ftp = MyFtp()
    # ftp.set_debuglevel(2)
    try:
        ftp.connect(host, port)
        ftp.login(username, password)
        print("*********************************************************", ftp.getwelcome())
    except ConnectionRefusedError as e:
        print("ftp服務連接失敗!")
        connectStatus = False
    return connectStatus, ftp


def downloadfile(ip, port, remotepath, localpath):
    # ftp連接
    connectStatus, ftp = ftpconnect(ip, port, "xxx", "xxx")
    if not connectStatus:
        pass
    try:
        # 從ftp下載文件
        bufsize = 1024
        fp = open(localpath, 'wb')
        ftp.retrbinary('RETR ' + remotepath, fp.write, bufsize)
        ftp.set_debuglevel(0)
        fp.close()
    except EOFError as e:
        print("FTP服務異常更卒,傳輸失數确酢!")
    except ConnectionAbortedError as e:
        print("FTP服務異常逞壁,傳輸失斄骷谩锐锣!")
    except TimeoutError as e:
        print("FTP服務異常腌闯,傳輸失敗雕憔!")
    except Exception as e:
        print("FTP服務異常姿骏,傳輸失敗斤彼!")

def uploadfile(ip, port, localpath, remotepath):
    # ftp連接
    connectStatus, ftp = ftpconnect(ip, port, "xxx", "xxx")
    if not connectStatus:
        pass
    try:
        # 從本地上傳文件到ftp
        bufsize = 1024
        fp = open(localpath, 'rb')
        ftp.storbinary('STOR ' + remotepath, fp, bufsize)
        ftp.set_debuglevel(0)
        fp.close()
        ftp.quit()
    except EOFError as e:
        print("FTP服務異常分瘦,傳輸失斦盒骸!")
    except ConnectionAbortedError as e:
        print("FTP服務異常嘲玫,傳輸失斣檬!")
    except TimeoutError as e:
        print("FTP服務異常去团,傳輸失斅盏!")
    except Exception as e:
        print("FTP服務異常土陪,傳輸失斨绾埂!")


import time
if __name__ == "__main__":

    ip = "xxxxx"
    port = xxx # 可以是云服務的21端口鬼雀,也可以是服務器21端口映射到外網(wǎng)的端口

    local_file = r'F:\videos\2023-02-04_01-58-09.mp4'
    for i in range(5):
        target_file = str(i) + 'a.mp4'
        try:
            uploadfile(ip, port, local_file, target_file)
        except Exception as e:
            print(e)
        time.sleep(5)
        # downloadfile(ftp, "VID_20210830_103249.mp4", "11.mp4")


本次過程中出現(xiàn)的錯誤:
①主動模式:ftplib.error_perm: 501 Rejected data connection to foreign address 192.168.1.xxx.11.
②被動模式顷窒,卡在resp '227 Entering passive mode (192,168,1,1x,xx,xxx).'

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市源哩,隨后出現(xiàn)的幾起案子鞋吉,更是在濱河造成了極大的恐慌,老刑警劉巖璧疗,帶你破解...
    沈念sama閱讀 218,755評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件坯辩,死亡現(xiàn)場離奇詭異,居然都是意外死亡崩侠,警方通過查閱死者的電腦和手機漆魔,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來却音,“玉大人改抡,你說我怎么就攤上這事∠灯埃” “怎么了阿纤?”我有些...
    開封第一講書人閱讀 165,138評論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長夷陋。 經(jīng)常有香客問我欠拾,道長,這世上最難降的妖魔是什么骗绕? 我笑而不...
    開封第一講書人閱讀 58,791評論 1 295
  • 正文 為了忘掉前任藐窄,我火速辦了婚禮,結(jié)果婚禮上酬土,老公的妹妹穿的比我還像新娘荆忍。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 67,794評論 6 392
  • 文/花漫 我一把揭開白布刹枉。 她就那樣靜靜地躺著叽唱,像睡著了一般。 火紅的嫁衣襯著肌膚如雪微宝。 梳的紋絲不亂的頭發(fā)上棺亭,一...
    開封第一講書人閱讀 51,631評論 1 305
  • 那天,我揣著相機與錄音蟋软,去河邊找鬼侦铜。 笑死,一個胖子當著我的面吹牛钟鸵,可吹牛的內(nèi)容都是我干的钉稍。 我是一名探鬼主播,決...
    沈念sama閱讀 40,362評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼棺耍,長吁一口氣:“原來是場噩夢啊……” “哼贡未!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起蒙袍,我...
    開封第一講書人閱讀 39,264評論 0 276
  • 序言:老撾萬榮一對情侶失蹤俊卤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后害幅,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體消恍,經(jīng)...
    沈念sama閱讀 45,724評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年以现,在試婚紗的時候發(fā)現(xiàn)自己被綠了狠怨。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,040評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡邑遏,死狀恐怖佣赖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情记盒,我是刑警寧澤憎蛤,帶...
    沈念sama閱讀 35,742評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站纪吮,受9級特大地震影響俩檬,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜碾盟,卻給世界環(huán)境...
    茶點故事閱讀 41,364評論 3 330
  • 文/蒙蒙 一棚辽、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧巷疼,春花似錦晚胡、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至骡尽,卻和暖如春遣妥,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背攀细。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評論 1 270
  • 我被黑心中介騙來泰國打工箫踩, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人谭贪。 一個月前我還...
    沈念sama閱讀 48,247評論 3 371
  • 正文 我出身青樓境钟,卻偏偏與公主長得像,于是被迫代替她去往敵國和親俭识。 傳聞我的和親對象是個殘疾皇子慨削,可洞房花燭夜當晚...
    茶點故事閱讀 44,979評論 2 355

推薦閱讀更多精彩內(nèi)容