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 初始化多维数组代码
Sep 06 Python
Python中关于使用模块的基础知识
May 24 Python
python二分查找算法的递归实现方法
May 12 Python
windows上安装Anaconda和python的教程详解
Mar 28 Python
Python 中 list 的各项操作技巧
Apr 13 Python
使用pandas的DataFrame的plot方法绘制图像的实例
May 24 Python
解决Mac安装scrapy失败的问题
Jun 13 Python
python之信息加密题目详解
Jun 26 Python
使用Pycharm(Python工具)新建项目及创建Python文件的教程
Apr 26 Python
Python如何定义有可选参数的元类
Jul 31 Python
python 爬取吉首大学网站成绩单
Jun 02 Python
Python turtle实现贪吃蛇游戏
Jun 18 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模板,主要想体现一下思路
2006/12/25 PHP
php根据身份证号码计算年龄的实例代码
2014/01/18 PHP
php实现设计模式中的单例模式详解
2014/10/11 PHP
php基于base64解码图片与加密图片还原实例
2014/11/03 PHP
YII分模块加载路由的实现方法
2018/10/01 PHP
window.name代替cookie的实现代码
2010/11/28 Javascript
js去除输入框中所有的空格和禁止输入空格的方法
2014/06/09 Javascript
使用jquery+CSS3实现仿windows10开始菜单的下拉导航菜单特效
2015/09/24 Javascript
Jquery日历插件制作简单日历
2015/10/28 Javascript
js文件中直接alert()中文出来的是乱码的解决方法
2016/11/01 Javascript
详解nodejs express下使用redis管理session
2017/04/24 NodeJs
jQuery基于Ajax实现读取XML数据功能示例
2018/05/31 jQuery
react中实现搜索结果中关键词高亮显示
2018/07/31 Javascript
js中innerText/textContent和innerHTML与target和currentTarget的区别
2019/01/21 Javascript
利用Promise自定义一个GET请求的函数示例代码
2019/03/20 Javascript
AntV F2和vue-cli构建移动端可视化视图过程详解
2019/10/08 Javascript
小程序实现日历左右滑动效果
2019/10/21 Javascript
Vue 实现把表单form数据 转化成json格式的数据
2019/10/29 Javascript
如何正确理解vue中的key详解
2019/11/02 Javascript
Python文件操作,open读写文件,追加文本内容实例
2016/12/14 Python
用Python写一段用户登录的程序代码
2018/04/22 Python
Python实现使用卷积提取图片轮廓功能示例
2018/05/12 Python
Python根据成绩分析系统浅析
2019/02/11 Python
pandas的相关系数与协方差实例
2019/12/27 Python
django haystack实现全文检索的示例代码
2020/06/24 Python
python中查看.db文件中表格的名字及表格中的字段操作
2020/07/07 Python
将HTML5 Canvas的内容保存为图片借助toDataURL实现
2013/05/20 HTML / CSS
Casadei卡萨蒂官网:意大利奢侈鞋履品牌
2017/10/28 全球购物
几个人围成一圈的问题
2013/09/26 面试题
急诊科护士自我鉴定
2013/10/14 职场文书
三峡大坝导游词
2015/01/31 职场文书
绍兴鲁迅故居导游词
2015/02/09 职场文书
大学生暑期实践报告
2015/07/13 职场文书
小学体育组工作总结
2015/08/13 职场文书
导游词之苏州盘门景区
2019/11/12 职场文书
Python基础之字符串格式化详解
2021/04/21 Python