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