python实现ftp文件传输系统(案例分析)


Posted in Python onMarch 20, 2020

最近做了一个简单的文件传输系统,基于ftp协议,使用python语言开发,虽然python里面已经有ftplib模块,可以很容易的实现ftp服务器。这次我使用的是socket实现client与ftp server之间的通讯和文件传输,client另起一个flask服务器,用于用户在浏览器端的交互。系统实现的功能有:用户登录注册,用户查看ftp服务器端文件和下载上传删除操作,支持多进程、多用户。

一,登录注册

         该项目使用的是mongo数据库,其实用户登录注册功能很好实现,没有什么技术细节,这里就略过了。数据库管理代码如下:

import pymongo
from pymongo.collection import Collection
class DBManager(object):
 def __init__(self):
  client = pymongo.MongoClient("mongodb://localhost:27017/")
  self.db = client["FTPDB"]
  self.users = self.db['user']
 #保存用户登录信息
 def saveUserInfo(self,account,password):
  users = self.users.find()
  for item in users:
   accountDB = item['account']
   if accountDB == account:
    return "false"
  data = []
  userInfo = {}
  userInfo['account'] = account
  userInfo['password'] = password
  data.append(userInfo)
  collection = Collection(self.db,"user")
  collection.insert(data)
  return "true"
 def confirmUserLoginInfo(self,account,password):
  users = self.users.find()
  '''
   result状态: 1:表示初始状态,即不存在用户
      2:表示存在该用户、密码不正确
      3:验证成功
  '''
  result = 1
  for item in users:
   accountDB = item['account']
   passwordDB = item['password']
   if accountDB == account:
    if passwordDB == password:
     result = 3
    else:
     result = 2
  return result

前端注册js代码如下:

function register() {
 account = $("#account").val();
 password = $("#password").val();
 confirmPassword = $("#confirmPassword").val();
 if(account == null || password == null || confirmPassword == null){
  alert("请先输入必要信息")
  return;
 }
 if(password != confirmPassword){
  alert("密码不一致");
  return;
 }
 var request = {
  type:"register",
  account:account,
  password:password
 }
 sendData("http://localhost:8080/register",request)
}
//向服务器发送数据
function sendData(url,json) {
 $.ajax({
  url: url, //请求的url地址
  dataType: "json", //返回格式为json
  async: true, //请求是否异步,默认为异步,这也是ajax重要特性
  data: json, //参数值
  type: "post", //请求方式
  success:function(data){
   //alert(data)
   if(data.toString() == "false"){
    alert("用户名已存在");
   }else{
    window.location.href = "http://localhost:8080/index";
   }
  },
  error:function (error) {
   console.log(error);
  }
 });
}

二,文件管理(文件查看、删除、上传、下载)

客户端与服务器端约定命令格式,服务器通过解析客户端命令来执行操作。

server.py
from socket import *
import os,sys
import signal
import time
# 全局变量
HOST = '0.0.0.0'
PORT = 8686
ADDR = (HOST,PORT)
FILE_PATH = '../serverFiles/'
# 处理僵尸进程
signal.signal(signal.SIGCHLD,signal.SIG_IGN)
# 服务端功能类
class Server(object):
 def __init__(self):
  self.connfd = ""
 def do_list(self,account):
  # 获取文件列表
  file_list = os.listdir(FILE_PATH+account)
  if not file_list:
   self.connfd.send("服务器文件库为空".encode())
   return
  else:
   self.connfd.send(b"OK")
   time.sleep(0.1)
  files = ""
  for file in file_list:
   if file[0] != '.' and os.path.isfile(FILE_PATH + account +"/"+ file):
    files += file + '#'
  self.connfd.send(files.encode())
 def delete(self,accout,fileName):
  os.remove(FILE_PATH + accout + "/" + fileName)
  self.connfd.send(b"OK")
  time.sleep(0.1)
 def do_get(self,account,filename):
  try:
   fd = open(FILE_PATH + account +"/"+ filename,'rb')
  except IOError:
   self.connfd.send("文件不存在".encode())
   return
  else:
   #print("发送OK")
   self.connfd.send(b'OK')
   time.sleep(0.1)
  # 发送文件内容
  while True:
   data = fd.read(1024)
   if not data:
    time.sleep(0.1)
    self.connfd.send(b'##')
    break
   #print("正在发送数据")
   self.connfd.send(data)
  fd.close()
 def do_put(self,account,filename):
  if os.path.exists(FILE_PATH + account +"/"+ filename):
   self.connfd.send('该文件已存在'.encode())
   return
  fd = open(FILE_PATH + account +"/"+ filename,'wb')
  self.connfd.send(b'OK')
  # 接收文件内容
  while True:
   data = self.connfd.recv(1024)
   if data == b'**':
    break
   fd.write(data)
  fd.close()
 def socket_tcp(self):
  s = socket()
  s.setsockopt(SOL_SOCKET,SO_REUSEADDR,True)
  s.bind(ADDR)
  s.listen(5)
  print("Listen the port 8686...")
  return s
 def do_request(self,connfd):
  self.connfd = connfd
  while True:
   data = connfd.recv(1024).decode()
   datas = data.split(' ')
   if not data or datas[1] == 'QUIT@#':
    connfd.close()
    return
   elif datas[1] == "LIST@#":
    #print("list")
    self.do_list(datas[0])
   elif datas[1] == 'GET@#':
    filename = datas[-1]
    self.do_get(datas[0],filename)
   elif datas[1] == 'PUT@#':
    filename = datas[-1]
    self.do_put(datas[0],filename)
   elif datas[1] == 'delete@#':
    filename = datas[-1]
    self.delete(datas[0],filename)
 def run(self):
  # 创建套接字
  s = self.socket_tcp()
  while True:
   try:
    connfd,addr = s.accept()
   except KeyboardInterrupt:
    sys.exit("服务器退出")
   except Exception as e:
    print(e)
    continue
   print("Connect from",addr)
   # 创建子进程
   pid = os.fork()
   if pid == 0:
    s.close()
    self.do_request(connfd) #处理客户端具体请求
    os._exit(0)
   else:
    connfd.close()
if __name__ == "__main__":
 server = Server()
 server.run()
client.py
"""
 client.py
"""
import socket
import os,sys
import time
# 服务器地址
ADDR = ("127.0.0.1",8686)
FILE_PATH = "./clientFiles/"
# 客户端功能类
class Client(object):
 def __init__(self,account):
  self.sockfd = ""
  self.account = account
 #获得服务器文件列表
 def server_list(self):
  ftpServerFiles = []
  self.sockfd.send((self.account+' LIST@# ').encode())
  # 等待回复
  data = self.sockfd.recv(128).decode()
  if data == "OK":
   files = self.sockfd.recv(4096).decode()
   for file in files.split('#'):
    #print(file)
    ftpServerFiles.append(file)
  else:
   # 无法完成操作
   print(data)
  ftpServerFiles = ftpServerFiles[:-1]
  return ftpServerFiles
 #获得用户文件夹列表
 def client_list(self):
  # 获取文件列表
  userFiles = []
  file_list = os.listdir(FILE_PATH+self.account+"/")
  if not file_list:
   return
  else:
   time.sleep(0.1)
  files = ""
  for file in file_list:
   if file[0] != '.' and os.path.isfile(FILE_PATH + self.account + "/" + file):
    userFiles.append(file)
  return userFiles
 #退出
 def do_quit(self):
  self.sockfd.send((self.account+' QUIT@# ').encode())
  self.sockfd.close()
  sys.exit('谢谢使用')
 #用户下载服务器文件
 def do_get(self,filename):
  self.sockfd.send((self.account+' GET@# '+filename).encode())
  data = self.sockfd.recv(128).decode()
  if data == 'OK':
   fd = open(FILE_PATH + self.account + "/" + filename,'wb')
   #复写
   while True:
    data = self.sockfd.recv(1024)
    if data == b'##':
     #print("##")
     break
    #print("正在写入数据")
    fd.write(data)
   fd.close()
  else:
   print(data)
 #用户将文件上传到服务器文件夹
 def do_put(self,filename):
  try:
   fd = open(FILE_PATH + self.account + "/" + filename,'rb')
  except IOError:
   print("文件不存在")
   return
  # 获取文件名
  filename = filename.split('/')[-1]
  # else:
  self.sockfd.send((self.account+' PUT@# '+filename).encode())
  data = self.sockfd.recv(128).decode()
  # 发送文件
  if data == 'OK':
   while True:
    data = fd.read(1024)
    if not data:
     time.sleep(0.1)
     self.sockfd.send(b'**')
     break
    self.sockfd.send(data)
   fd.close()
   return "true"
  else:
   print(data)
   return "false"
 #删除用户文件
 def removeU(self,fileName):
  os.remove(FILE_PATH + self.account + "/" + fileName)
  return "true"
 #删除用户文件
 def removeF(self,fileName):
  self.sockfd.send((self.account+' delete@# '+fileName).encode())
  # 等待回复
  data = self.sockfd.recv(128).decode()
  if data == "OK":
   return "true"
 def menu_display(self):
  print("\n------命令选择-------")
  print("*** clist  ***")
  print("*** slist  ***")
  print("*** get list  ***")
  print("*** put list  ***")
  print("*** quit  ***")
  print("----------------------")
 def run(self,cmd):
  # 创建套接字
  sockfd = socket.socket()
  try:
   sockfd.connect(ADDR)
  except Exception as e:
   print(e)
   return
  result = ""
  self.sockfd = sockfd
  # choice(cmd,ftp)
  if cmd == "slist":
   result = self.server_list()
   return result
  elif cmd == "clist":
   result = self.client_list()
   return result
  elif cmd =='quit':
   self.do_quit()
  elif cmd[:3] == 'get':
   filename = cmd.strip().split(' ')[-1]
   self.do_get(filename)
  elif cmd[:3] == 'put':
   filename = cmd.strip().split(' ')[-1]
   result = self.do_put(filename)
   return result
  elif cmd[:7] == 'removeU':
   filename = cmd.strip().split(' ')[-1]
   self.removeU(filename)
  elif cmd[:7] == 'removeF':
   filename = cmd.strip().split(' ')[-1]
   self.removeF(filename)
  else:
   print("请输入正确命令!")
if __name__ == "__main__":
 client = Client("ffy")
 client.run()

运行界面:

python实现ftp文件传输系统(案例分析)

python实现ftp文件传输系统(案例分析) 

总结 

到此这篇关于python实现ftp文件传输系统的文章就介绍到这了,更多相关python ftp文件传输内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Python 相关文章推荐
python基础教程之面向对象的一些概念
Aug 29 Python
Python使用multiprocessing实现一个最简单的分布式作业调度系统
Mar 14 Python
Python win32com 操作Exce的l简单方法(必看)
May 25 Python
django 创建过滤器的实例详解
Aug 14 Python
Python程序运行原理图文解析
Feb 10 Python
Python基于Floyd算法求解最短路径距离问题实例详解
May 16 Python
python3.X 抓取火车票信息【修正版】
Jun 19 Python
Python清空文件并替换内容的实例
Oct 22 Python
详解python实现交叉验证法与留出法
Jul 11 Python
pytorch在fintune时将sequential中的层输出方法,以vgg为例
Aug 20 Python
Python实现发票自动校核微信机器人的方法
May 22 Python
Python3 requests模块如何模仿浏览器及代理
Jun 15 Python
关于Python 中的时间处理包datetime和arrow的方法详解
Mar 19 #Python
JetBrains PyCharm(Community版本)的下载、安装和初步使用图文教程详解
Mar 19 #Python
Python文件操作基础流程解析
Mar 19 #Python
Python函数基本使用原理详解
Mar 19 #Python
Python ATM功能实现代码实例
Mar 19 #Python
详解django使用include无法跳转的解决方法
Mar 19 #Python
Django模板标签中url使用详解(url跳转到指定页面)
Mar 19 #Python
You might like
AJAX的跨域访问-两种有效的解决方法介绍
2013/06/22 PHP
JoshChen_php新手进阶高手不可或缺的规范介绍
2013/08/16 PHP
ThinkPHP2.x防范XSS跨站攻击的方法
2015/09/25 PHP
php实现word转html的方法
2016/01/22 PHP
Smarty3配置及入门语法
2017/02/22 PHP
js里取容器大小、定位、距离等属性搜集整理
2013/08/19 Javascript
js window.print实现打印特定控件或内容
2013/09/16 Javascript
JS删除字符串中重复字符方法
2014/03/09 Javascript
DOM基础教程之事件对象
2015/01/20 Javascript
jQuery实现动态表单验证时文本框抖动效果完整实例
2015/08/21 Javascript
基于jQuery实现响应式圆形图片轮播特效
2015/11/25 Javascript
JQuery EasyUI学习教程之datagrid 添加、修改、删除操作
2016/07/09 Javascript
Vue分页组件实例代码
2017/04/17 Javascript
JavaScript文件的同步和异步加载的实现代码
2017/08/19 Javascript
requireJS模块化实现返回顶部功能的方法详解
2017/10/16 Javascript
jQuery进阶实践之利用最优雅的方式如何写ajax请求
2017/12/20 jQuery
基于 D3.js 绘制动态进度条的实例详解
2018/02/26 Javascript
jQuery实现数字自动增加或者减少的动画效果示例
2018/12/11 jQuery
WebSocket的简单介绍及应用
2019/05/23 Javascript
在vue项目实现一个ctrl+f的搜索功能
2020/02/28 Javascript
微信小程序自定义扫码功能界面的实现代码
2020/07/02 Javascript
[02:24]DOTA2痛苦女王 英雄基础教程
2013/11/26 DOTA
Python使用爬虫猜密码
2016/02/19 Python
wxPython的安装图文教程(Windows)
2017/12/28 Python
Python之ReportLab绘制条形码和二维码的实例
2018/01/15 Python
python使用thrift教程的方法示例
2019/03/21 Python
django中账号密码验证登陆功能的实现方法
2019/07/15 Python
html如何对span设置宽度
2019/10/30 HTML / CSS
草莓网官网:StrawberryNET
2019/08/21 全球购物
皇家阿尔伯特瓷器美国官网:Royal Albert美国
2020/02/16 全球购物
建筑行业的大学生自我评价
2013/12/08 职场文书
村班子对照检查材料
2014/08/18 职场文书
银行业务授权委托书
2014/10/10 职场文书
再见,2019我们不负使命;你好,2020我们砥砺前行
2020/01/03 职场文书
利用ajax+php实现商品价格计算
2021/03/31 PHP
「约定的梦幻岛」作画发布诺曼生日新绘
2022/03/21 日漫