python实现支持目录FTP上传下载文件的方法


Posted in Python onJune 03, 2015

本文实例讲述了python实现支持目录FTP上传下载文件的方法。分享给大家供大家参考。具体如下:

该程序支持ftp上传下载文件和目录、适用于windows和linux平台。

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import ftplib
import os
import sys
class FTPSync(object):
  conn = ftplib.FTP()
  def __init__(self,host,port=21):    
    self.conn.connect(host,port)    
  def login(self,username,password):
    self.conn.login(username,password)
    self.conn.set_pasv(False)
    print self.conn.welcome
  def test(self,ftp_path):
    print ftp_path
    print self._is_ftp_dir(ftp_path)
    #print self.conn.nlst(ftp_path)
    #self.conn.retrlines( 'LIST ./a/b')
    #ftp_parent_path = os.path.dirname(ftp_path)
    #ftp_dir_name = os.path.basename(ftp_path)
    #print ftp_parent_path
    #print ftp_dir_name
  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 ftplib.error_perm,e:
      return False
  def _ftp_list(self, line):
    list = line.split(' ')
    if self.ftp_dir_name==list[-1] and list[0].startswith('d'):
      self._is_dir = True
  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:
      #this ues callback function ,that will change _is_dir value
      try:
        self.conn.retrlines('LIST %s' %ftp_parent_path,self._ftp_list)
      except ftplib.error_perm,e:
        return self._is_dir    
    return self._is_dir
  def get_file(self,ftp_path,local_path='.'):
    ftp_path = ftp_path.rstrip('/')
    if self._is_ftp_file(ftp_path):    
      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)
    else:
      print 'EROOR:The ftp file:%s is not exist' %ftp_path
  def put_file(self,local_path,ftp_path='.'):
    ftp_path = ftp_path.rstrip('/')
    if os.path.isfile( local_path ):           
      file_handler = open(local_path, "r")
      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 'STOR %s'%ftp_path        
        self.conn.storbinary('STOR %s'%ftp_path, file_handler)
      #如果远程路径不是目录,且上一层的目录也不存在,则提示给定远程路径错误
      else:        
        print 'EROOR:The ftp path:%s is error' %ftp_path
      file_handler.close()
    else:
      print 'ERROR:The file:%s is not exist' %local_path
  def get_dir(self,ftp_path,local_path='.',begin=True): 
    ftp_path = ftp_path.rstrip('/')
    #当ftp目录存在时下载    
    if self._is_ftp_dir(ftp_path):
      #如果下载到本地当前目录下,并创建目录
      #下载初始化:如果给定的本地路径不存在需要创建,同时将ftp的目录存放在给定的本地目录下。
      #ftp目录下文件存放的路径为local_path=local_path+os.path.basename(ftp_path)
      #例如:将ftp文件夹a下载到本地的a/b目录下,则ftp的a目录下的文件将下载到本地的a/b/a目录下
      if begin:
        if not os.path.isdir(local_path):
          os.makedirs(local_path)
        local_path=os.path.join(local_path,os.path.basename(ftp_path))
      #如果本地目录不存在,则创建目录
      if not os.path.isdir(local_path):
        os.makedirs(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的标志修改为False)
        #如果file ftp路径是文件则直接上传文件
        if self._is_ftp_dir(file):
          self.get_dir(file,local_file,False)
        else:
          self.get_file(file,local_file)
      #如果当前ftp目录文件已经遍历完毕返回上一层目录
      self.conn.cwd( ".." )
      return
    else:
      print 'ERROR:The dir:%s is not exist' %ftp_path
      return

  def put_dir(self,local_path,ftp_path='.',begin=True):
    ftp_path = ftp_path.rstrip('/')
    #当本地目录存在时上传
    if os.path.isdir(local_path):      
      #上传初始化:如果给定的ftp路径不存在需要创建,同时将本地的目录存放在给定的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):
          self.conn.mkd(ftp_path)
        ftp_path=os.path.join(ftp_path,os.path.basename(local_path))          
      #如果ftp路径不是目录,则创建目录
      if not self._is_ftp_dir(ftp_path):
        self.conn.mkd(ftp_path)

      #进入本地目录,开始递归查询
      os.chdir(local_path)
      local_files = os.listdir('.')
      for file in local_files:
        #如果file本地路径是目录则递归上传目录(不需要再进行初始化begin的标志修改为False)
        #如果file本地路径是文件则直接上传文件
        if os.path.isdir(file):          
          ftp_path=os.path.join(ftp_path,file)
          self.put_dir(file,ftp_path,False)
        else:
          self.put_file(file,ftp_path)
      #如果当前本地目录文件已经遍历完毕返回上一层目录
      os.chdir( ".." )
    else:
      print 'ERROR:The dir:%s is not exist' %local_path
      return
if __name__ == '__main__':
  ftp = FTPSync('192.168.1.110')
  ftp.login('test','test')
  #上传文件,不重命名
  #ftp.put_file('111.txt','a/b')
  #上传文件,重命名
  #ftp.put_file('111.txt','a/112.txt')
  #下载文件,不重命名
  #ftp.get_file('/a/111.txt',r'D:\\')
  #下载文件,重命名
  #ftp.get_file('/a/111.txt',r'D:\112.txt')
  #下载到已经存在的文件夹
  #ftp.get_dir('a/b/c',r'D:\\a')
  #下载到不存在的文件夹
  #ftp.get_dir('a/b/c',r'D:\\aa')
  #上传到已经存在的文件夹
  ftp.put_dir('b','a')
  #上传到不存在的文件夹
  ftp.put_dir('b','aa/B/')

希望本文所述对大家的Python程序设计有所帮助。

Python 相关文章推荐
python网络编程学习笔记(六):Web客户端访问
Jun 09 Python
python监控网站运行异常并发送邮件的方法
Mar 13 Python
Python功能键的读取方法
May 28 Python
Python找出9个连续的空闲端口
Feb 01 Python
python的一些加密方法及python 加密模块
Jul 11 Python
Django框架模型简单介绍与使用分析
Jul 18 Python
python自动结束mysql慢查询会话的实例代码
Oct 27 Python
Django1.11自带分页器paginator的使用方法
Oct 31 Python
基于python实现检索标记敏感词并输出
May 07 Python
Python实现疫情通定时自动填写功能(附代码)
May 27 Python
PyTorch的torch.cat用法
Jun 28 Python
keras在构建LSTM模型时对变长序列的处理操作
Jun 29 Python
python实现的DES加密算法和3DES加密算法实例
Jun 03 #Python
python获取各操作系统硬件信息的方法
Jun 03 #Python
wxPython定时器wx.Timer简单应用实例
Jun 03 #Python
Python基于DES算法加密解密实例
Jun 03 #Python
Python使用minidom读写xml的方法
Jun 03 #Python
Python实现程序的单一实例用法分析
Jun 03 #Python
python简单获取本机计算机名和IP地址的方法
Jun 03 #Python
You might like
PHP函数篇之掌握ord()与chr()函数应用
2011/12/05 PHP
Laravel 5 框架入门(三)
2015/04/09 PHP
Symfony生成二维码的方法
2016/02/04 PHP
深入理解PHP之源码目录结构与功能说明
2016/06/01 PHP
PHPMailer发送邮件
2016/12/28 PHP
php/JS实现的生成随机密码(验证码)功能示例
2019/06/06 PHP
关于laravel5.5的定时任务详解(demo)
2019/10/23 PHP
JavaScript怎么判断图片是否加载完成以便获取其尺寸
2014/05/08 Javascript
jquery滚动加载数据的方法
2015/03/09 Javascript
Javascript中的call()方法介绍
2015/03/15 Javascript
jQuery实现获取table表格第一列值的方法
2016/03/01 Javascript
JS实现添加,替换,删除节点元素的方法
2016/06/30 Javascript
Spring MVC中Ajax实现二级联动的简单实例
2016/07/06 Javascript
基于JavaScript实现移动端无限加载分页
2017/03/27 Javascript
详解vue-cli中配置sass
2017/06/21 Javascript
JavaScript正则表达式和级联效果
2017/09/14 Javascript
JS打印彩色菱形的实例代码
2018/08/15 Javascript
解决Vue打包后访问图片/图标不显示的问题
2019/07/25 Javascript
vue实现点击按钮“查看详情”弹窗展示详情列表操作
2020/09/09 Javascript
python异步存储数据详解
2019/03/19 Python
python 缺失值处理的方法(Imputation)
2019/07/02 Python
python计算Content-MD5并获取文件的Content-MD5值方式
2020/04/03 Python
python PIL模块的基本使用
2020/09/29 Python
Europcar美国/加拿大:预订汽车或卡车租赁服务
2018/11/13 全球购物
法国二手MacBook销售网站:Okamac
2019/03/18 全球购物
会计系中文个人求职信
2013/12/24 职场文书
社区禁毒工作方案
2014/06/02 职场文书
消防安全宣传口号
2014/06/10 职场文书
2014财务部年度工作总结
2014/12/08 职场文书
小学语文教师年度考核个人总结
2015/02/05 职场文书
写给媳妇的检讨书
2015/05/06 职场文书
因工资原因离职的辞职信范文
2015/05/12 职场文书
实践论读书笔记
2015/06/29 职场文书
房地产置业顾问工作总结
2015/10/23 职场文书
2016教师暑期培训学习心得体会
2016/01/09 职场文书
SpringBoot2 参数管理实践之入参出参与校验的方式
2021/06/16 Java/Android