File size: 3,608 Bytes
3205dff
a460fdc
 
146248c
b86f530
 
059bbb9
0b67e3c
146248c
 
5bb5d81
 
059bbb9
b86f530
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
be00d02
5bb5d81
 
 
 
33f8f7c
5bb5d81
 
b86f530
 
3205dff
5bb5d81
 
b86f530
 
 
 
 
5bb5d81
b86f530
 
5bb5d81
a71ce8a
 
b86f530
5bb5d81
3205dff
b86f530
 
5bb5d81
b86f530
 
 
 
 
3205dff
b86f530
3205dff
 
 
5bb5d81
b86f530
5bb5d81
 
b86f530
 
 
 
 
 
 
 
 
 
 
 
 
a71ce8a
b86f530
 
 
 
 
5bb5d81
a71ce8a
 
 
b86f530
 
 
 
a71ce8a
059bbb9
0b67e3c
b86f530
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 threading
import time
from datetime import datetime, timedelta

app = Flask(__name__)

transfers = {}
transfer_data = {}
transfer_lock = threading.Lock()

# Настройки хранения данных
TRANSFER_LIFETIME = timedelta(hours=1)  # Время хранения завершенных передач
CLEANUP_INTERVAL = 3600  # 5 минут в секундах

def cleanup_task():
    """Фоновая задача для очистки старых передач"""
    while True:
        time.sleep(CLEANUP_INTERVAL)
        with transfer_lock:
            now = datetime.now()
            to_delete = []
            for transfer_id, info in transfers.items():
                if info['completed'] and (now - info['completed_time']) > TRANSFER_LIFETIME:
                    to_delete.append(transfer_id)
            
            for transfer_id in to_delete:
                del transfers[transfer_id]
                del transfer_data[transfer_id]

threading.Thread(target=cleanup_task, daemon=True).start()

def generate_short_id(length=4):
    while True:
        token = ''.join(random.choices(string.ascii_letters + string.digits, k=length))
        if token not in transfers:
            return token

@app.route('/create_transfer', methods=['POST'])
def create_transfer():
    data = request.json
    transfer_id = generate_short_id()
    
    with transfer_lock:
        transfers[transfer_id] = {
            'filename': data['filename'],
            'filesize': data.get('filesize', 0),
            'completed': False,
            'created_time': datetime.now(),
            'completed_time': None
        }
        transfer_data[transfer_id] = []
    
    return jsonify({'transfer_id': transfer_id})

@app.route('/upload/<transfer_id>', methods=['POST'])
def upload_chunk(transfer_id):
    if transfer_id not in transfers:
        return jsonify({'error': 'Invalid transfer ID'}), 404

    chunk = request.data
    with transfer_lock:
        transfer_data[transfer_id].append(chunk)
        
        if request.headers.get('X-Transfer-Complete') == 'true':
            transfers[transfer_id]['completed'] = True
            transfers[transfer_id]['completed_time'] = datetime.now()
    
    return jsonify({'status': 'chunk accepted'})

@app.route('/download/<transfer_id>', methods=['GET'])
def download_file(transfer_id):
    def generate():
        index = 0
        while True:
            with transfer_lock:
                transfer = transfers.get(transfer_id)
                if not transfer:
                    break
                
                chunks = transfer_data.get(transfer_id, [])
                
                # Отправляем все новые чанки
                while index < len(chunks):
                    yield chunks[index]
                    index += 1
                
                # Проверяем завершение передачи
                if transfer['completed']:
                    break
            
            time.sleep(1)  # Ожидание новых чанков

    if transfer_id not in transfers:
        return jsonify({'error': 'Transfer not found'}), 404

    return Response(
        generate(),
        mimetype='application/octet-stream',
        headers={
            'Content-Disposition': f'attachment; filename="{transfers[transfer_id]["filename"]}"',
            'Transfer-Encoding': 'chunked'
        }
    )

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000, threaded=True)