基于Socket的Python FTP传输脚本:传输成功但目标服务器无文件
问题诊断与解决方案
为啥文件传了却找不到?
你写的脚本根本没遵循FTP协议规则,导致vsftpd完全识别不了你发的是要保存的文件:
- FTP分控制连接(端口21)和数据连接:控制连接只用来发命令(比如登录、上传指令),文件内容得通过单独的数据连接传输,你直接在控制连接里塞文件数据,服务器只会把这些当乱码,不会存成文件。
- 缺失关键命令:上传文件必须先告诉服务器「我要传二进制文件」(
TYPE I)、「建立数据连接」(PASV或PORT)、「我要传这个文件,名叫XXX」(STOR 文件名),你脚本里完全没这些步骤。 - 无效的文件标识:你发的
{file_path}{filesize}格式服务器根本看不懂,它不知道这是文件名还是其他乱码。
修正后的两种脚本方案
方案1:原生Socket实现标准FTP上传
手动处理FTP协议的所有步骤,适合学习底层逻辑:
#!/bin/python3 import socket import os def main(): file_path = input("enter the absolute_file_path of the file you want to upload: ") filename = os.path.basename(file_path) # 只提取文件名,不要完整路径 filesize = os.path.getsize(file_path) # 建立控制连接(端口21) s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect(('192.168.190.130', 21)) print(s.recv(1024).decode('utf-8')) # 登录服务器 s.send(b'USER harsh\r\n') print(s.recv(1024).decode('utf-8')) s.send(b'PASS iacsd@123\r\n') print(s.recv(1024).decode('utf-8')) # 设置二进制传输模式,避免文件损坏 s.send(b'TYPE I\r\n') print(s.recv(1024).decode('utf-8')) # 用被动模式建立数据连接(大部分FTP服务器默认支持) s.send(b'PASV\r\n') pasv_response = s.recv(1024).decode('utf-8') print(pasv_response) # 解析被动模式返回的地址和端口 pasv_parts = pasv_response.split('(')[1].split(')')[0].split(',') data_ip = '.'.join(pasv_parts[:4]) data_port = int(pasv_parts[4]) * 256 + int(pasv_parts[5]) # 建立数据连接 data_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) data_sock.connect((data_ip, data_port)) # 告诉服务器要上传的文件名 s.send(f'STOR {filename}\r\n'.encode('utf-8')) print(s.recv(1024).decode('utf-8')) # 传输文件内容 BUFFER_SIZE = 4096 with open(file_path, 'rb') as f: while True: bytes_read = f.read(BUFFER_SIZE) if not bytes_read: break data_sock.sendall(bytes_read) # 关闭连接收尾 data_sock.close() print(s.recv(1024).decode('utf-8')) s.send(b'QUIT\r\n') print(s.recv(1024).decode('utf-8')) s.close() print("File uploaded successfully.") if __name__ == '__main__': main()
方案2:用内置ftplib库(省心又靠谱)
你已经导入了ftplib,直接用它能省掉手动处理协议的繁琐细节:
#!/bin/python3 import ftplib import os def main(): file_path = input("enter the absolute_file_path of the file you want to upload: ") filename = os.path.basename(file_path) try: # 连接FTP服务器并登录 ftp = ftplib.FTP('192.168.190.130') ftp.login(user='harsh', passwd='iacsd@123') # 设置二进制传输模式 ftp.voidcmd('TYPE I') # 上传文件 with open(file_path, 'rb') as f: ftp.storbinary(f'STOR {filename}', f) print("File uploaded successfully.") ftp.quit() except Exception as e: print(f"上传失败:{str(e)}") if __name__ == '__main__': main()
额外检查点
- 确认vsftpd配置:确保
write_enable=YES(允许写入文件)、local_umask=022(保证上传文件权限正常),且用户harsh对自己的FTP主目录(默认是/home/harsh/)有写入权限。 - 查找文件位置:上传的文件默认保存在
harsh的主目录下,直接去/home/harsh/路径查找即可。
内容的提问来源于stack exchange,提问作者Harsh
相关产品推荐
相关产品推荐

