python3 FTP上传文件
最简单的FTP上次文件
# TCP服务端_server.py import socket import struct sk = socket.socket() # 创建socket对象 sk.bind(("127.0.0.1", 6666)) # 绑定IP和端口号 sk.listen() # 开启监听 print("开启监听!") conn, address = sk.accept() # 等待客户端连接 阻塞 print("客户端连接成功!") file_size = struct.unpack("i", conn.recv(4))[0] f = open("upload/flower.jpg", "wb") while file_size > 0: msg = conn.recv(1024) f.write(msg) file_size -= len(msg) conn.close() sk.close()
# TCP客户端_client.py import socket import struct import os sk = socket.socket() # 创建socket对象 sk.connect(("127.0.0.1", 6666)) # 连接服务端 file_name = "timg.jpg" file_size = os.path.getsize(file_name) sk.send(struct.pack("i", file_size)) with open(file_name, "rb") as f: for line in f: sk.send(line) print(f"文件{file_name}上传完成!") sk.close()
注意:
先执行服务端,再执行客户端,最后会在upload文件夹下看到你上传的文件。
将文件大小和文件名放入字典中,先发送字典转字符串的字节长度,再发送字典转字符串后的字节
# TCP服务端_server.py import socket import struct import json sk = socket.socket() # 创建socket对象 sk.bind(("127.0.0.1", 6666)) # 绑定IP和端口号 sk.listen() # 开启监听 print("开启监听!") conn, address = sk.accept() # 等待客户端连接 阻塞 print("客户端连接成功!") dic_json_len = struct.unpack("i", conn.recv(4))[0] # 先接收json字符串长度 dic_json = conn.recv(dic_json_len).decode("utf-8") # 接收json字符串 dic = json.loads(dic_json) # 转化为字典 file_size = dic.get("file_size") # 文件大小 file_name = dic.get("file_name") # 文件名 f = open(f"upload/{file_name}", "wb") # 以rb模式写文件 while file_size > 0: # 循环接收文件内容 msg = conn.recv(1024) f.write(msg) file_size -= len(msg) conn.close() sk.close()
# TCP客户端_client.py import socket import struct import json import os sk = socket.socket() # 创建socket对象 sk.connect(("127.0.0.1", 6666)) # 连接服务端 file_name = "timg.jpg" # 文件名 file_size = os.path.getsize(file_name) # 文件大小 dic = {"file_name": file_name, "file_size": file_size} # 将文件名和文件大小放入字典中 dic_json_str = json.dumps(dic) # 将字典转化为json字符串 dic_bs = dic_json_str.encode("utf-8") # 对json字符串进行编码,转化为字节 sk.send(struct.pack("i", len(dic_bs))) # 先发送json字符串的长度 sk.send(dic_bs) # 在发送json字节 with open(file_name, "rb") as f: # 以rb模式读取要上传的文件 for line in f: sk.send(line) # 逐行发送文件内容 print(f"文件{file_name}上传完成!") sk.close()
注意:
先执行服务端,后执行客户端,最后会在upload文件夹看到你上传的同名文件。
即便是视频文件,也是可以按行来读取的,也可以readline,也可以for循环,但是读取出来的数据大小就不固定了,影响效率,有可能读的比较小,
也可能很大,像视频文件一般都是一行的二进制字节流。
所有我们可以用read,设定一个一次读取内容的大小,一边读一边发,一边收一边写。
-------------------------------------ftp_server.py-------------------------------------
# coding:utf-8
import json
import socket
import struct
server = socket.socket()
ip_port = ("127.0.0.1", 8001)
buffer = 1024
server.bind(ip_port)
server.listen(5)
conn, addr = server.accept()
header_len = conn.recv(4) # 接收报头长度
header_bytes = conn.recv(struct.unpack('i', header_len)[0]) # 接收报头
header = json.loads(header_bytes.decode("utf-8")) # 报头解码->反序列化
file_size = header['filesize'] # 文件的大小
print(file_size, buffer)
with open(header['filename'], "wb") as f:
while file_size:
if file_size >= buffer:
f.write(conn.recv(buffer))
file_size -= buffer
print(file_size, buffer)
else:
f.write(conn.recv(buffer))
print(file_size, buffer)
break
conn.close()
server.close()
-------------------------------------ftp_client.py-------------------------------------
# coding:utf-8
import os
import json
import struct
import socket
client = socket.socket()
ip_port = ("127.0.0.1", 8001)
client.connect(ip_port)
buffer = 1024
header = { # 报头为dict类型
"filename": "day08.md",
"filepath": r"F:\2019老男孩周末26期\day08\课下练习",
"filesize": 0,
}
file_path = os.path.join(header['filepath'], header['filename'])
file_size = os.path.getsize(file_path)
header['filesize'] = file_size
header_json = json.dumps(header) # 报头序列化为json字符串
header_bytes = header_json.encode("utf-8") # 报头编码为bytes类型
client.send(struct.pack('i', len(header_bytes))) # 发送4个字节的报头大小
client.send(header_bytes) # 发送报头
print(file_size, buffer)
with open(file_path, "rb") as f:
while file_size:
if file_size >= buffer:
client.send(f.read(buffer))
file_size -= buffer
print(file_size, buffer, "第一次或中间的")
else:
client.send(f.read(buffer))
print(file_size, buffer, "最后一次")
break
client.close()