python实现ftp文件传输功能


Posted in Python onMarch 20, 2020

本文实例为大家分享了python实现ftp文件传输的具体代码,供大家参考,具体内容如下

主要步骤可以分为以下几步:

1.读取文件名
2.检测文件是否存在
3.打开文件
4.检测文件大小
5.发送文件大小和 md5值给客户端
6.等客户端确认
7.开始边读边发数据

服务器端代码:

import socket,os,time
import hashlib
 
server =socket.socket()
server.bind(('0.0.0.0',6666))
server.listen()
print("等待....")
while True:
 conn,addr = server.accept()
 print("new conn:",conn)
 while True:
 data = conn.recv(1024)
 if not data:
 print("client is disconnection")
 break
 cmd,filename = data.decode().split() #记录指令和文件名
 print(filename)
 #判断当前目录是否存在该文件,而且必须是文件,而不是目录
 if os.path.isfile(filename):
 f = open(filename,'rb')
 #m = hashlib.md5() # 创建md5
 file_size = os.stat(filename).st_size #stat() 可以返回文件的大小值
 conn.send((str(file_size)).encode()) # 发送文件大小
 conn.recv(1024) #等待返回信息
 for line in f:
 # m.updata(line) 
 conn.send(line)
 #print("file md5",m.hexdigest()) #打印md5值
 f.close()

客户端代码:

# Author: zjt
import socket
 
client = socket.socket()
 
client.connect(("0.0.0.0",6666))
 
 
while True:
 cmd = input(">>>:").strip()
 
 if len(cmd)==0 :continue
 
 if cmd.startswith("get"):
 client.send(cmd.encode())
 server_response = client.recv(1024)
 print("server response: ",server_response)
 client.send(b"ready to recv file")
 
 # 开始接收文件
 file_total_size = int(server_response.decode())
 received_size = 0 # 记录接收文件的大小
 filename = cmd.split()[1]
 # 因为两个目录一致,接收的文件名不能与原文件相同
 f = open(filename+".new","wb")
 while received_size < file_total_size:
 data = client.recv(1024)
 received_size += len(data)
 f.write(data)
 print("total:",file_total_size," present: ",received_size)
 else:
 print("file has received done!")
 f.close()
 
client.close()

用80M的文件传输测试,效果如下:

python实现ftp文件传输功能

程序升级:

前面的代码还没添加md5进行验证,现在对代码进行升级

服务器端代码:

import socket,os,time
import hashlib
 
server =socket.socket()
server.bind(('0.0.0.0',8888))
server.listen()
print("等待....")
while True:
 conn,addr = server.accept()
 print("new conn:",conn)
 while True:
 data = conn.recv(1024)
 if not data:
 print("client is disconnection")
 break
 cmd,filename = data.decode().split() #记录指令和文件名
 print(filename)
 #判断当前目录是否存在该文件,而且必须是文件,而不是目录
 if os.path.isfile(filename):
 f = open(filename,'rb')
 m = hashlib.md5() # 创建md5
 file_size = os.stat(filename).st_size #stat() 可以返回文件的大小值
 conn.send((str(file_size)).encode()) # 发送文件大小
 conn.recv(1024) #等待返回信息
 for line in f:
 m.update(line)
 conn.send(line)
 print("file md5",m.hexdigest()) #打印md5值
 
 f.close()
 conn.send(m.hexdigest().encode()) # 发送md5
 
 print("我真的已经发过去了",m.hexdigest().encode())
 
 print("send done")
 
server.close()

客户端代码:

import socket
import hashlib
client = socket.socket()
client.connect(("0.0.0.0",8888))
while True:
 cmd = input(">>>:").strip()
 if len(cmd)==0 :continue
 if cmd.startswith("get"):
 client.send(cmd.encode())
 server_response = client.recv(1024)
 print("server response: ",server_response)
 client.send(b"ready to recv file")
 # 开始接收文件
 file_total_size = int(server_response.decode())
 received_size = 0 # 记录接收文件的大小
 filename = cmd.split()[1]
 # 因为两个目录一致,接收的文件名不能与原文件相同
 f = open(filename+".new","wb")
 m = hashlib.md5()
 while received_size < file_total_size:
 data = client.recv(1024)
 received_size += len(data)
 m.update(data)
 f.write(data)
 #print("total:",file_total_size," present: ",received_size)
 else:
 new_file_md5 = m.hexdigest()
 print("client file md5:",new_file_md5)
 print("file has received done!")
 print("total:",file_total_size," present: ",received_size)
 f.close()
 sever_file_md5 = client.recv(1024)
 print("client file md5:",new_file_md5)
 print("server file md5:",sever_file_md5)
client.close()

两个程序在linux 环境下运行,结果如下:

python实现ftp文件传输功能

可以看到传输后文件大小变大了一点点,而且md5前后值也不同,说明文件传输发生了改变。

现在讲程序在windows环境下运行,结果如下:

python实现ftp文件传输功能

此时可以看到windows上没有问题,文件大小相同,且md5值也一致。

原因分析:

之所以会发生这种情况,是因为在linux上运行时,最后一次传输文件与发送md5值的时候,发生可粘包,导致最后一次接收文件的时候,连同md5的数据一并发送了。而客户端也当作一条接收信息,全部接收了。所以客户端出现没有收到来自服务器端的md5值,多出来的那一点点,就是md5值的大小。

解决方法:

在接收文件的时候,判断当前剩余多少文件需要接收,如果大于1024,就接收1024大小的文件,否则就只接收剩下全部的文件,防止最后一次接收多余的数据。

只需要对客户端代码进行修改,修改后代码如下:

import socket
import hashlib
client = socket.socket()
client.connect(("0.0.0.0",8888))
while True:
 cmd = input(">>>:").strip()
 if len(cmd)==0 :continue
 if cmd.startswith("get"):
 client.send(cmd.encode())
 server_response = client.recv(1024)
 print("server response: ",server_response)
 client.send(b"ready to recv file")
 # 开始接收文件
 file_total_size = int(server_response.decode())
 received_size = 0 # 记录接收文件的大小
 filename = cmd.split()[1]
 f = open(filename+".new","wb")
 m = hashlib.md5()
 while received_size < file_total_size:
 #添加一次判断,使最后一次剩多少就接收多少,避免发生粘包
 if file_total_size - received_size > 1024:
  size = 1024
 else: # 最后一次,剩多少收多少
  size = file_total_size - received_size
 data = client.recv(size)
 received_size += len(data)
 m.update(data)
 f.write(data)
 else:
 new_file_md5 = m.hexdigest() 
 print("client file md5:",new_file_md5)
 print("file has received done!")
 print("total:",file_total_size," present: ",received_size)
 print("下一句关闭文件")
 f.close()
 print("开始接收md5 ") 
 sever_file_md5 = client.recv(1024)
 print("client file md5:",new_file_md5)
 print("server file md5:",sever_file_md5)
client.close()

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
python操作数据库之sqlite3打开数据库、删除、修改示例
Mar 13 Python
python使用MySQLdb访问mysql数据库的方法
Aug 03 Python
Python使用pickle模块存储数据报错解决示例代码
Jan 26 Python
Python在groupby分组后提取指定位置记录方法
Apr 20 Python
Python中的取模运算方法
Nov 10 Python
python实现坦克大战游戏 附详细注释
Mar 27 Python
python基于递归解决背包问题详解
Jul 03 Python
Python字符串中添加、插入特定字符的方法
Sep 10 Python
Python如何基于smtplib发不同格式的邮件
Dec 30 Python
在 Python 中接管键盘中断信号的实现方法
Feb 04 Python
django教程如何自学
Jul 31 Python
python向企业微信发送文字和图片消息的示例
Sep 28 Python
Python开发之身份证验证库id_validator验证身份证号合法性及根据身份证号返回住址年龄等信息
Mar 20 #Python
python实现FTP文件传输的方法(服务器端和客户端)
Mar 20 #Python
python实现ftp文件传输系统(案例分析)
Mar 20 #Python
关于Python 中的时间处理包datetime和arrow的方法详解
Mar 19 #Python
JetBrains PyCharm(Community版本)的下载、安装和初步使用图文教程详解
Mar 19 #Python
Python文件操作基础流程解析
Mar 19 #Python
Python函数基本使用原理详解
Mar 19 #Python
You might like
逆序二维数组插入一元素的php代码
2012/06/08 PHP
PHP实现的多文件上传类及用法示例
2016/05/06 PHP
PHP实现表单提交数据的验证处理功能【防SQL注入和XSS攻击等】
2017/07/21 PHP
php让json_encode不自动转义斜杠“/”的方法
2020/04/27 PHP
FireFox下XML对象转化成字符串的解决方法
2011/12/09 Javascript
JQueryEasyUI datagrid框架的基本使用
2013/04/08 Javascript
jquery eval解析JSON中的注意点介绍
2013/08/23 Javascript
js定时调用方法成功后并停止调用示例
2014/04/08 Javascript
JavaScript动态创建div等元素实例讲解
2016/01/06 Javascript
JS获取鼠标相对位置的方法
2016/09/20 Javascript
js中获取 table节点各tr及td的内容简单实例
2016/10/14 Javascript
基于jQuery实现顶部导航栏功能
2016/12/27 Javascript
Vue计算属性的学习笔记
2017/03/22 Javascript
vue-cli的webpack模板项目配置文件分析
2017/04/01 Javascript
vue学习笔记之vue1.0和vue2.0的区别介绍
2017/05/17 Javascript
微信小程序 本地图片按照屏幕尺寸处理
2017/08/04 Javascript
react实现一个优雅的图片占位模块组件详解
2017/10/30 Javascript
微信小程序实时聊天WebSocket
2018/07/05 Javascript
iview同时验证多个表单问题总结
2018/09/29 Javascript
[03:13]DOTA2-DPC中国联赛1月25日Recap集锦
2021/03/11 DOTA
自己使用总结Python程序代码片段
2015/06/02 Python
python中list常用操作实例详解
2015/06/03 Python
python获取一组汉字拼音首字母的方法
2015/07/01 Python
如何在Python中编写并发程序
2016/02/27 Python
python 安装virtualenv和virtualenvwrapper的方法
2017/01/13 Python
Python实现对字典分别按键(key)和值(value)进行排序的方法分析
2018/12/19 Python
Python Image模块基本图像处理操作小结
2019/04/13 Python
python实现扫描局域网指定网段ip的方法
2019/04/16 Python
Python寻找路径和查找文件路径的示例
2019/07/10 Python
python FTP编程基础入门
2021/02/27 Python
HTML5离线应用与客户端存储的实现
2018/05/03 HTML / CSS
司机的工作范围及职责
2013/11/13 职场文书
幼儿园开学家长寄语
2014/01/19 职场文书
2014最新房贷收入证明范本
2014/09/12 职场文书
党员个人年度总结
2015/02/14 职场文书
用Python提取PDF表格的方法
2021/04/11 Python