python ftplib 實現(xiàn)文件夾的上傳下載

在網(wǎng)上找了好多都不靠譜雹顺,要不就是報錯要不就是只能創(chuàng)建個文件夾瘸恼,于是自己怒改了一個儿咱。


#! /usr/bin/env python2.7
# encoding=utf8
from ftplib import FTP,error_perm  # 加載ftp模塊
import os

class FTPSync(object):
    conn = FTP()

    def __init__(self,host,port=21):
        self.conn.connect(host,port)

    def login(self,username,password):
        self.conn.login(username,password)
        self.conn.encoding = "GB2312"
        self.conn.set_debuglevel(2)             #打開調(diào)試級別2,顯示詳細信息
        self.conn.set_pasv(True)
        #0主動模式 1 #被動模式
        print(self.conn.welcome)

    def _ftp_list(self,line):
        li = line.split(' ')
        if self.ftp_dir_name == li[-1] and "<DIR>" in li:
            self._is_dir = True

    def _is_ftp_file(self, ftp_path):
        try:
            if ftp_path in self.conn.nlst(os.path.dirname(ftp_path)):
                return True
            else:
                return False
        except error_perm as e:
            return False

    def _is_ftp_dir(self,ftp_path):
        """
        用來判斷所給的路徑是文件還是文件夾
        """
        ftp_path = ftp_path.rstrip('/')
        ftp_parent_path = os.path.dirname(ftp_path)
        self.ftp_dir_name = os.path.basename(ftp_path)
        self._is_dir = False
        if ftp_path == '.' or ftp_path == './' or ftp_path == '':
            self._is_dir = True
        else:
            try:
                self.conn.cwd(ftp_path)
                self._is_dir = True
                # self.conn.retrlines('LIST %s' %ftp_parent_path,self._ftp_list)
            except error_perm as e:
                return self._is_dir
        return self._is_dir


    def get_file(self,ftp_path="",local_path="."):
        print(ftp_path)
        ftp_path = ftp_path.rstrip('/')

        file_name = os.path.basename(ftp_path)

        # 如果本地路徑是目錄噪叙,下載文件到該目錄
        if os.path.isdir(local_path):
            file_handler = open(os.path.join(local_path,file_name),'wb')
            self.conn.retrbinary("RETR %s"%(ftp_path),file_handler.write)
            file_handler.close()

        # 如果本地路徑不是目錄渐裂,但上層目錄存在豺旬,則按照本地路徑的文件名作為下載的文件名稱
        elif os.path.isdir(os.path.dirname(local_path)):
            file_handler = open(local_path,'wb')
            self.conn.retrbinary("RETR %s"%(ftp_path),file_handler.write)
            file_handler.close()
        # 如果本地路徑不是目錄,且上層目錄不存在柒凉,則退出
        else:
            print('EROOR:The dir:%s is not exist' %os.path.dirname(local_path))


    def get_dir(self,ftp_path,local_path=".",begin=True):

        if not self._is_ftp_dir(ftp_path):
            self.get_file(ftp_path=ftp_path, local_path=local_path)
            return

        if begin:
            local_path = os.path.join(local_path, os.path.basename(ftp_path))

        #如果本地目錄不存在族阅,則創(chuàng)建目錄
        if not os.path.isdir(local_path):
            os.mkdir(local_path)

        #進入ftp目錄,開始遞歸查詢
        self.conn.cwd(ftp_path)

        ftp_files = self.conn.nlst()

        for file in ftp_files:
            local_file = os.path.join(local_path, file)
            #如果file ftp路徑是目錄則遞歸上傳目錄(不需要再進行初始化begin的標(biāo)志修改為False)
            #如果file ftp路徑是文件則直接上傳文件
            if self._is_ftp_dir(file):
                self.get_dir(file, local_file, False)
            elif "idea" in file:
                pass
            else:
                self.get_file(ftp_path=file, local_path=local_file)

        #如果當(dāng)前ftp目錄文件已經(jīng)遍歷完畢返回上一層目錄
        self.conn.cwd("..")

    def get_all_dir(self):
        ftp_files = self.conn.nlst()
        for file in ftp_files:
            self.get_dir(file,"D:\\ftp",True)

    def put_file(self,local_path,ftp_path="."):
        ftp_path = ftp_path.rstrip('/')
        if os.path.isfile(local_path):
            file_handler = open(local_path,'rb')
            local_file_name = os.path.basename(local_path)

            #如果遠程路徑是個目錄膝捞,則上傳文件到這個目錄坦刀,文件名不變
            if self._is_ftp_dir(ftp_path):
                self.conn.storbinary('STOR %s'%os.path.join(ftp_path,local_file_name), file_handler)

            #如果遠程路徑的上層是個目錄,則上傳文件绑警,文件名按照給定命名
            elif self._is_ftp_dir(os.path.dirname(ftp_path)):
                print('STOP %s'%ftp_path)
                self.conn.storbinary('STOR %s'%ftp_path, file_handler)
            #如果遠程路徑不是目錄求泰,且上一層的目錄也不存在,則提示給定遠程路徑錯誤
            else:
                print('STOR %s'%ftp_path, file_handler)

    def put_dir(self,local_path,ftp_path=".",begin=True):
        ftp_path = ftp_path.rstrip('/')

        if not os.path.isdir(local_path):
            print('ERROR:The dir:%s is not exist' %local_path)
            return

        #當(dāng)本地目錄存在時上傳
        #上傳初始化:如果給定的ftp路徑不存在需要創(chuàng)建计盒,同時將本地的目錄存放在給定的ftp目錄下。
        # 本地目錄下文件存放的路徑為ftp_path = ftp_path + os.path.basename(local_path)
        #例如芽丹,將本地的文件夾a上傳到ftp的a/b目錄下北启,則本地a目錄下的文件將上傳的ftp的a/b/a目錄下
        if begin:
            if not self._is_ftp_dir(ftp_path):
                try:
                    self.conn.mkd(ftp_path)
                except Exception,e:
                    pass
            ftp_path = os.path.join(ftp_path,os.path.basename(local_path))

        # 如果上傳路徑是文件夾,則創(chuàng)建目錄
        if not self._is_ftp_dir(ftp_path):
            try:
                self.conn.mkd(ftp_path)
            except Exception, e:
                pass

        #進入本地目錄,開始遞歸查詢
        os.chdir(local_path)
        local_files = os.listdir('.')
        for file in local_files:
            ftp_file = os.path.join(ftp_path,file)
            #如果file本地路徑是目錄則遞歸上傳文件(不需要再進行初始化begin的標(biāo)志修改為False)
            #如果file本地路徑是文件則直接上傳文件
            if os.path.isdir(file):
                self.put_dir(file,ftp_file,False)
            elif "idea" in file:
                pass
            else:
                self.put_file(file,ftp_path)

        #如果當(dāng)前本地目錄文件已經(jīng)遍歷完畢返回上一層目錄
        os.chdir('..')

if __name__ == "__main__":
    ftp = FTPSync('10.10.10.69')
    ftp.login('dong',"dong")
    # ftp.get_file("ftppath")
    # ftp.get_dir("ftppath","localpath",True)
    # ftp.get_dir("","",True)
    # ftp.get_all_dir("")
    ftp.put_file('/home/myscan/myscan/myscan/report_file/7/http___192.168.1.104_.html')
    # ftp.put_dir('/home/myscan/myscan/myscan/report_file/7', "/home/ftp_dong",begin=True)


最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末咕村,一起剝皮案震驚了整個濱河市场钉,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌懈涛,老刑警劉巖逛万,帶你破解...
    沈念sama閱讀 219,110評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異批钠,居然都是意外死亡宇植,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,443評論 3 395
  • 文/潘曉璐 我一進店門埋心,熙熙樓的掌柜王于貴愁眉苦臉地迎上來指郁,“玉大人,你說我怎么就攤上這事拷呆∠锌玻” “怎么了?”我有些...
    開封第一講書人閱讀 165,474評論 0 356
  • 文/不壞的土叔 我叫張陵茬斧,是天一觀的道長腰懂。 經(jīng)常有香客問我,道長项秉,這世上最難降的妖魔是什么绣溜? 我笑而不...
    開封第一講書人閱讀 58,881評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮伙狐,結(jié)果婚禮上涮毫,老公的妹妹穿的比我還像新娘。我一直安慰自己贷屎,他們只是感情好罢防,可當(dāng)我...
    茶點故事閱讀 67,902評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著唉侄,像睡著了一般咒吐。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上属划,一...
    開封第一講書人閱讀 51,698評論 1 305
  • 那天恬叹,我揣著相機與錄音,去河邊找鬼同眯。 笑死绽昼,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的须蜗。 我是一名探鬼主播硅确,決...
    沈念sama閱讀 40,418評論 3 419
  • 文/蒼蘭香墨 我猛地睜開眼目溉,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了菱农?” 一聲冷哼從身側(cè)響起缭付,我...
    開封第一講書人閱讀 39,332評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎循未,沒想到半個月后陷猫,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,796評論 1 316
  • 正文 獨居荒郊野嶺守林人離奇死亡的妖,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,968評論 3 337
  • 正文 我和宋清朗相戀三年绣檬,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片羔味。...
    茶點故事閱讀 40,110評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡河咽,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出赋元,到底是詐尸還是另有隱情忘蟹,我是刑警寧澤,帶...
    沈念sama閱讀 35,792評論 5 346
  • 正文 年R本政府宣布搁凸,位于F島的核電站媚值,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏护糖。R本人自食惡果不足惜褥芒,卻給世界環(huán)境...
    茶點故事閱讀 41,455評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望嫡良。 院中可真熱鬧锰扶,春花似錦、人聲如沸寝受。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,003評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽很澄。三九已至京闰,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間甩苛,已是汗流浹背蹂楣。 一陣腳步聲響...
    開封第一講書人閱讀 33,130評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留讯蒲,地道東北人痊土。 一個月前我還...
    沈念sama閱讀 48,348評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像墨林,于是被迫代替她去往敵國和親施戴。 傳聞我的和親對象是個殘疾皇子反浓,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,047評論 2 355

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