1 # _*_ coding: utf-8 _*_
2 #服务端ftp
3
4 import socket
5 import struct
6 import json
7 import os
8 import pickle
9 import subprocess
10 import hashlib
11
12 from conf import settings
13 from core.user_handler import UserHandle
14
15
16 class FTPServer():
17
18 def __init__(self, server_address, bind_and_listen=True):
19 self.server_address = server_address
20 self.socket = socket.socket(settings.address_family, settings.socket_type)
21 if bind_and_listen:
22 try:
23 self.server_bind()
24 self.server_listen()
25 except Exception:
26 self.server_close()
27
28 def server_bind(self):
29 allow_reuse_address = False
30 if allow_reuse_address:
31 self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
32 self.socket.bind(self.server_address)
33
34 def server_listen(self):
35 self.socket.listen(settings.listen_count)
36
37 def server_close(self):
38 self.socket.close()
39
40 def server_accept(self):
41 return self.socket.accept()
42
43 def conn_close(self, conn):
44 conn.close()
45
46 def getfile_md5(self):
47 '''获取文件的md5'''
48 return hashlib.md5(self.readfile()).hexdigest()
49
50 def readfile(self):
51 '''读取文件,得到文件内容的bytes类型'''
52 with open(self.file_path, 'rb') as f:
53 filedata = f.read()
54 return filedata
55
56 def send_filedata(self, exist_file_size=0):
57 """下载时,将文件打开,send(data)"""
58 with open(self.file_path, 'rb') as f:
59 f.seek(exist_file_size)
60 while True:
61 data = f.read(1024)
62 if data:
63 self.conn.send(data)
64 else:
65 break
66
67 def get(self, cmds):
68 '''
69 下载,首先查看文件是否存在,然后上传文件的报头大小,上传文件,以读的方式发开文件
70 找到下载的文件
71 发送 header_size
72 发送 header_bytes file_size
73 读文件 rb 发送 send(line)
74 若文件不存在,发送0 client提示:文件不存在
75 :param cmds:
76 :return:
77 '''
78 if len(cmds) > 1:
79 filename = cmds[1]
80 self.file_path = os.path.join(os.getcwd(), filename)
81 if os.path.isfile(self.file_path):
82 file_size = os.path.getsize(self.file_path)
83 obj = self.conn.recv(4)
84 exist_file_size = struct.unpack('i', obj)[0]
85 header = {
86 'filename': filename,
87 'filemd5': self.getfile_md5(),
88 'file_size': file_size
89 }
90 header_bytes = pickle.dumps(header)
91 self.conn.send(struct.pack('i', len(header_bytes)))
92 self.conn.send(header_bytes)
93 if exist_file_size: # 表示之前被下载过 一部分
94 if exist_file_size != file_size:
95 self.send_filedata(exist_file_size)
96 else:
97 print('