File size: 3,849 Bytes
3205dff a460fdc 3205dff 146248c 059bbb9 0b67e3c 146248c a71ce8a 146248c 3205dff 146248c a71ce8a 146248c 059bbb9 146248c 33f8f7c 3205dff 146248c a71ce8a 146248c 3205dff 146248c 3205dff 146248c 3205dff 146248c 3205dff 146248c a71ce8a 146248c 3205dff 146248c a71ce8a 3205dff a71ce8a 3205dff 146248c 3205dff a71ce8a 146248c a71ce8a 059bbb9 146248c 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 110 111 112 113 114 115 116 117 118 119 120 121 122 |
from flask import Flask, request, jsonify, Response
import random
import string
import os
import threading
import time
from pathlib import Path
app = Flask(__name__)
app.config['UPLOAD_FOLDER'] = 'temp_uploads'
Path(app.config['UPLOAD_FOLDER']).mkdir(exist_ok=True)
# Конфигурация памяти
MAX_MEMORY = 12 * 1024 * 1024 * 1024 # 12 GB
CHUNK_SIZE = 100 * 1024 * 1024 # 4 MB
MAX_FILE_SIZE = 20 * 1024 * 1024 * 1024 # 20 GB
transfers = {}
active_memory = 0
lock = threading.Lock()
class TransferManager:
def __init__(self):
self.transfers = {}
self.file_locks = {}
def create_transfer(self, filename, filesize):
if filesize > MAX_FILE_SIZE:
raise ValueError("File size exceeds maximum limit")
transfer_id = ''.join(random.choices(string.ascii_letters + string.digits, k=16))
file_path = os.path.join(app.config['UPLOAD_FOLDER'], transfer_id)
with lock:
self.transfers[transfer_id] = {
'filename': filename,
'filesize': filesize,
'received': 0,
'file_path': file_path,
'created_at': time.time(),
'status': 'uploading'
}
self.file_locks[transfer_id] = threading.Lock()
return transfer_id
manager = TransferManager()
@app.route('/init_upload', methods=['POST'])
def init_upload():
filename = request.json.get('filename')
filesize = request.json.get('filesize')
try:
transfer_id = manager.create_transfer(filename, filesize)
return jsonify({'transfer_id': transfer_id})
except Exception as e:
return jsonify({'error': str(e)}), 400
@app.route('/upload/<transfer_id>', methods=['POST'])
def upload_chunk(transfer_id):
if transfer_id not in manager.transfers:
return jsonify({'error': 'Invalid transfer ID'}), 404
chunk = request.data
chunk_size = len(chunk)
with lock:
transfer = manager.transfers[transfer_id]
if transfer['status'] != 'uploading':
return jsonify({'error': 'Transfer completed'}), 400
try:
with manager.file_locks[transfer_id], open(transfer['file_path'], 'ab') as f:
f.write(chunk)
transfer['received'] += chunk_size
if transfer['received'] >= transfer['filesize']:
transfer['status'] = 'ready'
return jsonify({
'received': transfer['received'],
'status': transfer['status']
})
except Exception as e:
return jsonify({'error': str(e)}), 500
@app.route('/download/<transfer_id>', methods=['GET'])
def download_file(transfer_id):
def generate():
file_path = manager.transfers.get(transfer_id, {}).get('file_path')
if not file_path or not os.path.exists(file_path):
yield b'File not found'
return
with open(file_path, 'rb') as f:
while True:
chunk = f.read(CHUNK_SIZE)
if not chunk:
break
yield chunk
# Автоочистка через 1 час
threading.Timer(3600, cleanup_transfer, args=[transfer_id]).start()
return Response(
generate(),
mimetype='application/octet-stream',
headers={'Content-Disposition': f'attachment; filename="{manager.transfers[transfer_id]["filename"]}"'}
)
def cleanup_transfer(transfer_id):
with lock:
if transfer_id in manager.transfers:
try:
os.remove(manager.transfers[transfer_id]['file_path'])
except:
pass
del manager.transfers[transfer_id]
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000, threaded=True) |