Python實現(xiàn)FTP文件傳輸?shù)膶嵗?/h1>
更新時間:2019年07月07日 11:19:28 作者:隨#心
在本篇文章里小編給各位分享的是關(guān)于Python實現(xiàn)FTP文件傳輸?shù)膶嵗约跋嚓P(guān)代碼,需要的朋友們學習下。
FTP一般流程
FTP對應PASV和PORT兩種訪問方式,分別為被動和主動,是針對FTP服務(wù)器端進行區(qū)分的,正常傳輸過程中21號端口用于指令傳輸,數(shù)據(jù)傳輸端口使用其他端口。
PASV:由客戶端發(fā)起數(shù)據(jù)傳輸請求,服務(wù)器端返回并攜帶數(shù)據(jù)端口,并且服務(wù)器端開始監(jiān)聽此端口等待數(shù)據(jù),為被動模式;
PORT:客戶端監(jiān)聽端口并向服務(wù)器端發(fā)起請求,服務(wù)器端主動連接此端口進行數(shù)據(jù)傳輸,為主動模式。

其中TYPE分兩種模式,I對應二進制模式、A對應ASCII模式;
PASV為客戶端發(fā)送請求,之后227為服務(wù)器端返回操作碼表示成功,并且后面帶有服務(wù)器端監(jiān)聽的端口:143x256(左移8位)+48
之后通過STOR命令進行數(shù)據(jù)下載,下載完成后返回226表示數(shù)據(jù)傳輸完成。
2. Python代碼實現(xiàn):
中文路徑問題:由于FTP支持ASCII編碼,Python ftplib中編碼方式使用latin-1,而window默認編碼方式為gbk,所以使用Python處理時需先將中文路徑編碼為gbk之后譯碼為latin-1字符;
上傳下載使用storline和retrline,對應二進制使用storbinary和retrbinary。對于stor類函數(shù)后面的參數(shù)fp表示接收一個文件對象,支持read方法,一般為打開需要上傳的源文件,而retr類函數(shù)后面的參數(shù)表示對于返回數(shù)據(jù)的處理方法。
從一個FTP服務(wù)器到另一個FTP服務(wù)器的數(shù)據(jù)傳輸:
利用本地電腦作為數(shù)據(jù)緩存,但并不將數(shù)據(jù)保存到硬盤,只在內(nèi)存中存儲進行數(shù)據(jù)傳輸;其中一端作為下載一端為數(shù)據(jù)上傳。
首先登陸兩個FTP服務(wù)器,transfercmd函數(shù)用于發(fā)送命令并返回已建立好連接的本地Socket,此時分別在兩個本地Socket進行數(shù)據(jù)的收發(fā)即可。
在測試中發(fā)現(xiàn),在發(fā)送完一個文件之后只有及時的關(guān)閉socket,21端口才會返回226,數(shù)據(jù)完成指示,這樣才可以循環(huán)下一個文件,在完成之后要退出FTP。
#coding=utf-8
import ftplib,os.path,os
import socket
f1=ftplib.FTP('172.16.2.76')
f2=ftplib.FTP('172.16.25.153')
class myFTP:
path='file/download/bbb/'
# ftplib中編碼使用latin-1
title='版本'.encode(encoding='gbk').decode(encoding='latin-1')
path1=path+title
localDir='E:\\ver\\fp\\'
path2='abc/edf/'
def __init__(self):
try:
f1.login('username','password')
except ftplib.error_perm:
print('f1 cannot loggin!')
return
try:
f2.login()
except ftplib.error_perm:
print('f2 cannot loggin!')
return
def ftpD(self):
filelist=[]
fileLIST=[]
filels=f1.retrlines('LIST %s'%(self.path1),callback=filelist.append)
f1.cwd(self.path1)
for file in filelist:
fileAttr=file.split(' ')
fileName=fileAttr[-1]
fileType=fileAttr[0][0]
if fileType=='-':
fileLIST.append(fileName)
for file in fileLIST:
path=self.localDir+file
f1.retrbinary('RETR %s'%(file),open(path,'wb').write)
print('%s download.....'%(file))
f1.quit()
def ftpU(self,fun=1):
os.chdir(self.localDir)
fileList=os.listdir()
# upload file
if fun==1:
for file in fileList:
path=self.path2
f2.storbinary('STOR %s'%(path+file),open(file,'rb'))
print('%s uploading......'%(file))
#delete file
if fun==0:
try:
for file in fileList:
path=self.path2
f2.delete(path+file)
print('%s delete......'%(file))
except ftplib.error_perm:
print('no file to delete!!')
return
f2.quit()
def test(self):
f1.cwd(self.path1)
f2.cwd(self.path2)
fileList=f1.nlst()
print(fileList)
for file in fileList:
print('transfer %s......'%(file))
f1.voidcmd('TYPE I')
f2.voidcmd('TYPE I')
sock1=f1.transfercmd('RETR %s'%(file))
sock2=f2.transfercmd('STOR %s'%(file))
while 1:
data=sock1.recv(1024)
sock2.sendall(data)
if len(data)==0:
break
# 數(shù)據(jù)發(fā)送完成后需關(guān)閉socket,服務(wù)器21端口才會有返回
sock1.close()
sock2.close()
res1=f1.getresp()
#print('f1 >> %s'%(res1))
res2=f2.getresp()
#print('f2 >> %s'%(res2))
f1.quit()
f2.quit()
if __name__=='__main__':
ftptest=myFTP()
ftptest.ftpU(0)
#ftptest.test()
#ftptest.ftpD()
相關(guān)文章
-
django連接Mysql中已有數(shù)據(jù)庫的方法詳解
眾所周知Django較為適合原生開發(fā),即通過該框架搭建一個全新的項目,通過在修改models.py來創(chuàng)建新的數(shù)據(jù)庫表,下面這篇文章主要給大家介紹了關(guān)于django連接Mysql中已有數(shù)據(jù)庫的相關(guān)資料,需要的朋友可以參考下 2022-05-05
-
Python代碼調(diào)用執(zhí)行shell踩坑解決
這篇文章主要為大家介紹了Python代碼調(diào)用執(zhí)行shell,踩過的坑解決方法,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪 2023-06-06
-
Django3.2 自動發(fā)現(xiàn)所有路由代碼詳解
這篇文章主要為大家介紹了Django自動發(fā)現(xiàn)所有路由的方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
2021-12-12
-
python?Pandas庫read_excel()參數(shù)實例詳解
人們經(jīng)常用pandas處理表格型數(shù)據(jù),時常需要讀入excel表格數(shù)據(jù),下面這篇文章主要給大家介紹了關(guān)于python?Pandas庫read_excel()參數(shù)的相關(guān)資料,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下 2022-07-07
-
Python產(chǎn)生Gnuplot繪圖數(shù)據(jù)的方法
今天小編就為大家分享一篇Python產(chǎn)生Gnuplot繪圖數(shù)據(jù)的方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧 2018-11-11
最新評論
FTP一般流程
FTP對應PASV和PORT兩種訪問方式,分別為被動和主動,是針對FTP服務(wù)器端進行區(qū)分的,正常傳輸過程中21號端口用于指令傳輸,數(shù)據(jù)傳輸端口使用其他端口。
PASV:由客戶端發(fā)起數(shù)據(jù)傳輸請求,服務(wù)器端返回并攜帶數(shù)據(jù)端口,并且服務(wù)器端開始監(jiān)聽此端口等待數(shù)據(jù),為被動模式;
PORT:客戶端監(jiān)聽端口并向服務(wù)器端發(fā)起請求,服務(wù)器端主動連接此端口進行數(shù)據(jù)傳輸,為主動模式。
其中TYPE分兩種模式,I對應二進制模式、A對應ASCII模式;
PASV為客戶端發(fā)送請求,之后227為服務(wù)器端返回操作碼表示成功,并且后面帶有服務(wù)器端監(jiān)聽的端口:143x256(左移8位)+48
之后通過STOR命令進行數(shù)據(jù)下載,下載完成后返回226表示數(shù)據(jù)傳輸完成。
2. Python代碼實現(xiàn):
中文路徑問題:由于FTP支持ASCII編碼,Python ftplib中編碼方式使用latin-1,而window默認編碼方式為gbk,所以使用Python處理時需先將中文路徑編碼為gbk之后譯碼為latin-1字符;
上傳下載使用storline和retrline,對應二進制使用storbinary和retrbinary。對于stor類函數(shù)后面的參數(shù)fp表示接收一個文件對象,支持read方法,一般為打開需要上傳的源文件,而retr類函數(shù)后面的參數(shù)表示對于返回數(shù)據(jù)的處理方法。
從一個FTP服務(wù)器到另一個FTP服務(wù)器的數(shù)據(jù)傳輸:
利用本地電腦作為數(shù)據(jù)緩存,但并不將數(shù)據(jù)保存到硬盤,只在內(nèi)存中存儲進行數(shù)據(jù)傳輸;其中一端作為下載一端為數(shù)據(jù)上傳。
首先登陸兩個FTP服務(wù)器,transfercmd函數(shù)用于發(fā)送命令并返回已建立好連接的本地Socket,此時分別在兩個本地Socket進行數(shù)據(jù)的收發(fā)即可。
在測試中發(fā)現(xiàn),在發(fā)送完一個文件之后只有及時的關(guān)閉socket,21端口才會返回226,數(shù)據(jù)完成指示,這樣才可以循環(huán)下一個文件,在完成之后要退出FTP。
#coding=utf-8 import ftplib,os.path,os import socket f1=ftplib.FTP('172.16.2.76') f2=ftplib.FTP('172.16.25.153') class myFTP: path='file/download/bbb/' # ftplib中編碼使用latin-1 title='版本'.encode(encoding='gbk').decode(encoding='latin-1') path1=path+title localDir='E:\\ver\\fp\\' path2='abc/edf/' def __init__(self): try: f1.login('username','password') except ftplib.error_perm: print('f1 cannot loggin!') return try: f2.login() except ftplib.error_perm: print('f2 cannot loggin!') return def ftpD(self): filelist=[] fileLIST=[] filels=f1.retrlines('LIST %s'%(self.path1),callback=filelist.append) f1.cwd(self.path1) for file in filelist: fileAttr=file.split(' ') fileName=fileAttr[-1] fileType=fileAttr[0][0] if fileType=='-': fileLIST.append(fileName) for file in fileLIST: path=self.localDir+file f1.retrbinary('RETR %s'%(file),open(path,'wb').write) print('%s download.....'%(file)) f1.quit() def ftpU(self,fun=1): os.chdir(self.localDir) fileList=os.listdir() # upload file if fun==1: for file in fileList: path=self.path2 f2.storbinary('STOR %s'%(path+file),open(file,'rb')) print('%s uploading......'%(file)) #delete file if fun==0: try: for file in fileList: path=self.path2 f2.delete(path+file) print('%s delete......'%(file)) except ftplib.error_perm: print('no file to delete!!') return f2.quit() def test(self): f1.cwd(self.path1) f2.cwd(self.path2) fileList=f1.nlst() print(fileList) for file in fileList: print('transfer %s......'%(file)) f1.voidcmd('TYPE I') f2.voidcmd('TYPE I') sock1=f1.transfercmd('RETR %s'%(file)) sock2=f2.transfercmd('STOR %s'%(file)) while 1: data=sock1.recv(1024) sock2.sendall(data) if len(data)==0: break # 數(shù)據(jù)發(fā)送完成后需關(guān)閉socket,服務(wù)器21端口才會有返回 sock1.close() sock2.close() res1=f1.getresp() #print('f1 >> %s'%(res1)) res2=f2.getresp() #print('f2 >> %s'%(res2)) f1.quit() f2.quit() if __name__=='__main__': ftptest=myFTP() ftptest.ftpU(0) #ftptest.test() #ftptest.ftpD()
相關(guān)文章
django連接Mysql中已有數(shù)據(jù)庫的方法詳解
眾所周知Django較為適合原生開發(fā),即通過該框架搭建一個全新的項目,通過在修改models.py來創(chuàng)建新的數(shù)據(jù)庫表,下面這篇文章主要給大家介紹了關(guān)于django連接Mysql中已有數(shù)據(jù)庫的相關(guān)資料,需要的朋友可以參考下2022-05-05Python代碼調(diào)用執(zhí)行shell踩坑解決
這篇文章主要為大家介紹了Python代碼調(diào)用執(zhí)行shell,踩過的坑解決方法,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-06-06Django3.2 自動發(fā)現(xiàn)所有路由代碼詳解
這篇文章主要為大家介紹了Django自動發(fā)現(xiàn)所有路由的方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助2021-12-12python?Pandas庫read_excel()參數(shù)實例詳解
人們經(jīng)常用pandas處理表格型數(shù)據(jù),時常需要讀入excel表格數(shù)據(jù),下面這篇文章主要給大家介紹了關(guān)于python?Pandas庫read_excel()參數(shù)的相關(guān)資料,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下2022-07-07Python產(chǎn)生Gnuplot繪圖數(shù)據(jù)的方法
今天小編就為大家分享一篇Python產(chǎn)生Gnuplot繪圖數(shù)據(jù)的方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-11-11