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)