Starchik1 commited on
Commit
3205dff
·
verified ·
1 Parent(s): a71ce8a

Update main.py

Browse files
Files changed (1) hide show
  1. main.py +82 -60
main.py CHANGED
@@ -1,87 +1,109 @@
1
- from flask import Flask, request, Response
2
  import random
3
  import string
4
- from collections import deque
5
- import threading
6
  import time
 
 
 
7
 
8
  app = Flask(__name__)
9
 
10
- transfers = {}
11
- transfer_lock = threading.Lock()
12
- BUFFER_SIZE = 5 # Максимальное количество хранимых чанков
 
 
13
 
14
- class TransferSession:
15
- def __init__(self, filename):
16
- self.filename = filename
17
- self.buffer = deque(maxlen=BUFFER_SIZE)
18
- self.completed = False
19
- self.event = threading.Event()
20
- self.last_activity = time.time()
21
 
22
- def generate_id():
23
- return ''.join(random.choices(string.ascii_letters + string.digits, k=8))
24
 
25
- @app.route('/start_upload', methods=['POST'])
26
- def start_upload():
27
- filename = request.json.get('filename', 'file.bin')
28
- transfer_id = generate_id()
 
 
 
29
 
30
  with transfer_lock:
31
- transfers[transfer_id] = TransferSession(filename)
 
 
 
 
 
 
 
 
 
 
32
 
33
- return {'transfer_id': transfer_id}
34
 
35
  @app.route('/upload/<transfer_id>', methods=['POST'])
36
  def upload_chunk(transfer_id):
37
- with transfer_lock:
38
- session = transfers.get(transfer_id)
39
- if not session:
40
- return {'error': 'Invalid transfer ID'}, 404
41
-
42
- chunk = request.data
43
- session.buffer.append(chunk)
44
- session.last_activity = time.time()
45
- session.event.set()
46
- session.event.clear()
47
-
48
- if request.headers.get('X-Transfer-Complete') == 'true':
49
- session.completed = True
50
 
51
- return {'status': 'chunk accepted'}
52
-
53
- @app.route('/download/<transfer_id>')
54
- def download_chunks(transfer_id):
55
- def generate():
56
  with transfer_lock:
57
- session = transfers.get(transfer_id)
58
- if not session:
59
- yield b'Transfer not found'
60
- return
61
 
 
 
 
 
 
 
 
 
 
 
62
  while True:
63
- while session.buffer:
64
- chunk = session.buffer.popleft()
65
- yield chunk
66
-
67
- if session.completed:
68
- break
69
-
70
- session.event.wait(timeout=30)
71
- if time.time() - session.last_activity > 60:
72
  break
73
-
74
- # Очистка через минуту после завершения
75
- time.sleep(60)
76
- with transfer_lock:
77
- if transfer_id in transfers:
78
- del transfers[transfer_id]
79
-
80
  return Response(
81
  generate(),
82
  mimetype='application/octet-stream',
83
- headers={'Content-Disposition': f'attachment; filename="{session.filename}"'}
 
 
 
84
  )
85
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
86
  if __name__ == '__main__':
87
  app.run(host='0.0.0.0', port=5000, threaded=True)
 
1
+ from flask import Flask, request, jsonify, Response
2
  import random
3
  import string
 
 
4
  import time
5
+ import threading
6
+ import os
7
+ from collections import defaultdict
8
 
9
  app = Flask(__name__)
10
 
11
+ # Конфигурация
12
+ MAX_MEMORY = 12 * 1024 * 1024 * 1024 # 12 GB
13
+ CHUNK_SIZE = 5 * 1024 * 1024 # 5 MB
14
+ FILE_STORAGE = "./temp_uploads"
15
+ os.makedirs(FILE_STORAGE, exist_ok=True)
16
 
17
+ active_transfers = defaultdict(dict)
18
+ transfer_lock = threading.Lock()
 
 
 
 
 
19
 
20
+ def generate_transfer_id():
21
+ return ''.join(random.choices(string.ascii_letters + string.digits, k=16))
22
 
23
+ @app.route('/init_upload', methods=['POST'])
24
+ def init_upload():
25
+ filename = request.json.get('filename')
26
+ filesize = request.json.get('filesize')
27
+
28
+ transfer_id = generate_transfer_id()
29
+ filepath = os.path.join(FILE_STORAGE, transfer_id)
30
 
31
  with transfer_lock:
32
+ active_transfers[transfer_id] = {
33
+ 'filename': filename,
34
+ 'filesize': filesize,
35
+ 'received': 0,
36
+ 'filepath': filepath,
37
+ 'created_at': time.time()
38
+ }
39
+
40
+ # Создаем пустой файл
41
+ with open(filepath, 'wb') as f:
42
+ f.truncate(filesize)
43
 
44
+ return jsonify({'transfer_id': transfer_id})
45
 
46
  @app.route('/upload/<transfer_id>', methods=['POST'])
47
  def upload_chunk(transfer_id):
48
+ if transfer_id not in active_transfers:
49
+ return jsonify({'error': 'Invalid transfer ID'}), 404
50
+
51
+ chunk = request.data
52
+ start = int(request.headers.get('Content-Range').split('-')[0])
53
+
54
+ filepath = active_transfers[transfer_id]['filepath']
55
+
56
+ try:
57
+ with open(filepath, 'r+b') as f:
58
+ f.seek(start)
59
+ f.write(chunk)
 
60
 
 
 
 
 
 
61
  with transfer_lock:
62
+ active_transfers[transfer_id]['received'] += len(chunk)
 
 
 
63
 
64
+ return jsonify({'status': 'success', 'received': active_transfers[transfer_id]['received']})
65
+
66
+ except Exception as e:
67
+ return jsonify({'error': str(e)}), 500
68
+
69
+ @app.route('/download/<transfer_id>', methods=['GET'])
70
+ def download_file(transfer_id):
71
+ def generate():
72
+ filepath = active_transfers[transfer_id]['filepath']
73
+ with open(filepath, 'rb') as f:
74
  while True:
75
+ chunk = f.read(CHUNK_SIZE)
76
+ if not chunk:
 
 
 
 
 
 
 
77
  break
78
+ yield chunk
79
+
80
+ # Удаляем файл после отправки
81
+ os.remove(filepath)
82
+ del active_transfers[transfer_id]
83
+
 
84
  return Response(
85
  generate(),
86
  mimetype='application/octet-stream',
87
+ headers={
88
+ 'Content-Disposition': f'attachment; filename="{active_transfers[transfer_id]["filename"]}"',
89
+ 'Content-Length': str(active_transfers[transfer_id]['filesize'])
90
+ }
91
  )
92
 
93
+ # Очистка зависших передач
94
+ def cleanup():
95
+ while True:
96
+ time.sleep(3600)
97
+ now = time.time()
98
+ for tid in list(active_transfers.keys()):
99
+ if now - active_transfers[tid]['created_at'] > 86400: # 24 часа
100
+ try:
101
+ os.remove(active_transfers[tid]['filepath'])
102
+ del active_transfers[tid]
103
+ except:
104
+ pass
105
+
106
+ threading.Thread(target=cleanup, daemon=True).start()
107
+
108
  if __name__ == '__main__':
109
  app.run(host='0.0.0.0', port=5000, threaded=True)