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

Update main.py

Browse files
Files changed (1) hide show
  1. main.py +74 -61
main.py CHANGED
@@ -1,109 +1,122 @@
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)
 
1
  from flask import Flask, request, jsonify, Response
2
  import random
3
  import string
 
 
4
  import os
5
+ import threading
6
+ import time
7
+ from pathlib import Path
8
 
9
  app = Flask(__name__)
10
+ app.config['UPLOAD_FOLDER'] = 'temp_uploads'
11
+ Path(app.config['UPLOAD_FOLDER']).mkdir(exist_ok=True)
12
 
13
+ # Конфигурация памяти
14
  MAX_MEMORY = 12 * 1024 * 1024 * 1024 # 12 GB
15
+ CHUNK_SIZE = 100 * 1024 * 1024 # 4 MB
16
+ MAX_FILE_SIZE = 20 * 1024 * 1024 * 1024 # 20 GB
17
+
18
+ transfers = {}
19
+ active_memory = 0
20
+ lock = threading.Lock()
21
 
22
+ class TransferManager:
23
+ def __init__(self):
24
+ self.transfers = {}
25
+ self.file_locks = {}
26
+
27
+ def create_transfer(self, filename, filesize):
28
+ if filesize > MAX_FILE_SIZE:
29
+ raise ValueError("File size exceeds maximum limit")
30
+
31
+ transfer_id = ''.join(random.choices(string.ascii_letters + string.digits, k=16))
32
+ file_path = os.path.join(app.config['UPLOAD_FOLDER'], transfer_id)
33
+
34
+ with lock:
35
+ self.transfers[transfer_id] = {
36
+ 'filename': filename,
37
+ 'filesize': filesize,
38
+ 'received': 0,
39
+ 'file_path': file_path,
40
+ 'created_at': time.time(),
41
+ 'status': 'uploading'
42
+ }
43
+ self.file_locks[transfer_id] = threading.Lock()
44
+
45
+ return transfer_id
46
 
47
+ manager = TransferManager()
 
48
 
49
  @app.route('/init_upload', methods=['POST'])
50
  def init_upload():
51
  filename = request.json.get('filename')
52
  filesize = request.json.get('filesize')
53
 
54
+ try:
55
+ transfer_id = manager.create_transfer(filename, filesize)
56
+ return jsonify({'transfer_id': transfer_id})
57
+ except Exception as e:
58
+ return jsonify({'error': str(e)}), 400
 
 
 
 
 
 
 
 
 
 
 
 
59
 
60
  @app.route('/upload/<transfer_id>', methods=['POST'])
61
  def upload_chunk(transfer_id):
62
+ if transfer_id not in manager.transfers:
63
  return jsonify({'error': 'Invalid transfer ID'}), 404
64
 
65
  chunk = request.data
66
+ chunk_size = len(chunk)
67
 
68
+ with lock:
69
+ transfer = manager.transfers[transfer_id]
70
+ if transfer['status'] != 'uploading':
71
+ return jsonify({'error': 'Transfer completed'}), 400
72
 
73
  try:
74
+ with manager.file_locks[transfer_id], open(transfer['file_path'], 'ab') as f:
 
75
  f.write(chunk)
76
+ transfer['received'] += chunk_size
77
 
78
+ if transfer['received'] >= transfer['filesize']:
79
+ transfer['status'] = 'ready'
80
+
81
+ return jsonify({
82
+ 'received': transfer['received'],
83
+ 'status': transfer['status']
84
+ })
85
  except Exception as e:
86
  return jsonify({'error': str(e)}), 500
87
 
88
  @app.route('/download/<transfer_id>', methods=['GET'])
89
  def download_file(transfer_id):
90
  def generate():
91
+ file_path = manager.transfers.get(transfer_id, {}).get('file_path')
92
+ if not file_path or not os.path.exists(file_path):
93
+ yield b'File not found'
94
+ return
95
+
96
+ with open(file_path, 'rb') as f:
97
  while True:
98
  chunk = f.read(CHUNK_SIZE)
99
  if not chunk:
100
  break
101
  yield chunk
102
 
103
+ # Автоочистка через 1 час
104
+ threading.Timer(3600, cleanup_transfer, args=[transfer_id]).start()
 
105
 
106
  return Response(
107
  generate(),
108
  mimetype='application/octet-stream',
109
+ headers={'Content-Disposition': f'attachment; filename="{manager.transfers[transfer_id]["filename"]}"'}
 
 
 
110
  )
111
 
112
+ def cleanup_transfer(transfer_id):
113
+ with lock:
114
+ if transfer_id in manager.transfers:
115
+ try:
116
+ os.remove(manager.transfers[transfer_id]['file_path'])
117
+ except:
118
+ pass
119
+ del manager.transfers[transfer_id]
 
 
 
 
 
 
120
 
121
  if __name__ == '__main__':
122
  app.run(host='0.0.0.0', port=5000, threaded=True)