File size: 3,509 Bytes
0491fc6
33f8f7c
 
0491fc6
 
56921b4
059bbb9
 
 
07d1566
0491fc6
 
56921b4
059bbb9
33f8f7c
 
 
 
 
 
56921b4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
07d1566
 
0491fc6
 
 
33f8f7c
0491fc6
 
 
 
56921b4
 
0491fc6
 
56921b4
0491fc6
 
 
 
 
56921b4
 
 
 
 
 
 
 
 
 
 
 
 
0491fc6
 
 
 
56921b4
 
 
 
 
 
 
 
0491fc6
 
56921b4
 
0491fc6
56921b4
0491fc6
56921b4
 
 
 
 
07d1566
56921b4
 
 
0491fc6
 
 
56921b4
 
 
 
0491fc6
059bbb9
 
56921b4
 
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
from flask import Flask, request, jsonify, Response
import random
import string
from collections import deque
import threading
from datetime import datetime, timedelta

app = Flask(__name__)

transfers = {}
transfer_data = {}
transfer_lock = threading.Lock()
CLEANUP_INTERVAL = 300  # 5 минут

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

def cleanup_old_transfers():
    while True:
        now = datetime.now()
        with transfer_lock:
            to_delete = []
            for transfer_id, data in transfers.items():
                if now - data['last_activity'] > timedelta(seconds=CLEANUP_INTERVAL):
                    to_delete.append(transfer_id)
            
            for transfer_id in to_delete:
                del transfers[transfer_id]
                del transfer_data[transfer_id]
        
        threading.Event().wait(CLEANUP_INTERVAL)

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

@app.route('/upload/<transfer_id>', methods=['POST'])
def upload_file(transfer_id):
    with transfer_lock:
        if transfer_id not in transfers:
            return jsonify({'error': 'Invalid transfer ID'}), 404
        
        transfers[transfer_id]['last_activity'] = datetime.now()
        
        data = request.data
        if data:
            transfer_data[transfer_id].append(data)
        
        if request.headers.get('X-Transfer-Complete') == 'true':
            transfers[transfer_id]['completed'] = True
        
        return jsonify({'status': 'OK', 'received': len(data)})

@app.route('/download/<transfer_id>', methods=['GET'])
def download_file(transfer_id):
    def generate():
        with transfer_lock:
            if transfer_id not in transfers:
                return
            
            transfers[transfer_id]['last_activity'] = datetime.now()
            transfer = transfers[transfer_id]
            data_queue = transfer_data[transfer_id]
        
        while True:
            with transfer_lock:
                if data_queue:
                    chunk = bytes(data_queue.popleft())
                    yield chunk
                elif transfer['completed']:
                    break
                else:
                    # Ждем новые данные
                    pass
            
            threading.Event().wait(0.1)

    if transfer_id not in transfers:
        return jsonify({'error': 'Invalid transfer ID'}), 404
    
    return Response(
        generate(),
        mimetype='application/octet-stream',
        headers={
            'Content-Disposition': f'attachment; filename="{transfers[transfer_id]["filename"]}"',
            'Content-Length': str(transfers[transfer_id]['filesize'])
        }
    )

if __name__ == '__main__':
    threading.Thread(target=cleanup_old_transfers, daemon=True).start()
    app.run(host='0.0.0.0', port=7860, threaded=True)