Update app.py
Browse files
app.py
CHANGED
|
@@ -1,5 +1,5 @@
|
|
| 1 |
import flask
|
| 2 |
-
from flask import Flask, render_template_string, request, redirect, url_for, session, flash, send_file, jsonify, Response
|
| 3 |
from flask_caching import Cache
|
| 4 |
import json
|
| 5 |
import os
|
|
@@ -476,9 +476,14 @@ TMA_DASHBOARD_HTML_TEMPLATE = '''
|
|
| 476 |
document.getElementById('modalContent').innerHTML = '';
|
| 477 |
document.getElementById('modal-download-btn').style.display = 'none';
|
| 478 |
}
|
| 479 |
-
|
| 480 |
async function initiateDownload(fileId) {
|
| 481 |
haptic.impactOccurred('medium');
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 482 |
try {
|
| 483 |
const response = await fetch(`{{ url_for('download_tma', file_id='__FILE_ID__') }}`.replace('__FILE_ID__', fileId));
|
| 484 |
const data = await response.json();
|
|
@@ -490,6 +495,11 @@ TMA_DASHBOARD_HTML_TEMPLATE = '''
|
|
| 490 |
}
|
| 491 |
} catch (error) {
|
| 492 |
Telegram.WebApp.showAlert('Сетевая ошибка при создании ссылки для скачивания.');
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 493 |
}
|
| 494 |
}
|
| 495 |
|
|
@@ -771,14 +781,13 @@ def download_tma(file_id):
|
|
| 771 |
return jsonify({'status': 'error', 'message': 'Файл не найден или доступ запрещен'}), 404
|
| 772 |
|
| 773 |
token = uuid.uuid4().hex
|
| 774 |
-
cache.set(f"download_token_{token}", file_node, timeout=
|
| 775 |
public_url = url_for('public_download', token=token, _external=True)
|
| 776 |
return jsonify({'status': 'success', 'url': public_url})
|
| 777 |
|
| 778 |
@app.route('/public_download/<token>')
|
| 779 |
def public_download(token):
|
| 780 |
file_node = cache.get(f"download_token_{token}")
|
| 781 |
-
cache.delete(f"download_token_{token}")
|
| 782 |
if not file_node:
|
| 783 |
return Response("Ссылка для скачивания недействительна или истекла.", status=404)
|
| 784 |
|
|
@@ -788,23 +797,33 @@ def public_download(token):
|
|
| 788 |
return Response("Ошибка: Путь к файлу не найден.", status=500)
|
| 789 |
|
| 790 |
try:
|
| 791 |
-
|
| 792 |
-
|
| 793 |
-
|
| 794 |
-
|
| 795 |
-
|
| 796 |
-
|
| 797 |
-
)
|
| 798 |
-
|
| 799 |
-
|
| 800 |
-
|
| 801 |
-
|
| 802 |
-
|
| 803 |
-
|
| 804 |
-
|
| 805 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 806 |
except Exception as e:
|
| 807 |
-
logging.error(f"Error
|
| 808 |
return Response(f'Ошибка скачивания файла: {e}', status=502)
|
| 809 |
|
| 810 |
@app.route('/batch_download_tma')
|
|
@@ -1318,7 +1337,7 @@ def admin_download_file(tma_user_id_str, file_id):
|
|
| 1318 |
return jsonify({'status': 'error', 'message': 'File not found or access denied!'}), 404
|
| 1319 |
|
| 1320 |
token = uuid.uuid4().hex
|
| 1321 |
-
cache.set(f"download_token_{token}", file_node, timeout=
|
| 1322 |
public_url = url_for('public_download', token=token, _external=True)
|
| 1323 |
return jsonify({'status': 'success', 'url': public_url})
|
| 1324 |
|
|
|
|
| 1 |
import flask
|
| 2 |
+
from flask import Flask, render_template_string, request, redirect, url_for, session, flash, send_file, jsonify, Response, stream_with_context
|
| 3 |
from flask_caching import Cache
|
| 4 |
import json
|
| 5 |
import os
|
|
|
|
| 476 |
document.getElementById('modalContent').innerHTML = '';
|
| 477 |
document.getElementById('modal-download-btn').style.display = 'none';
|
| 478 |
}
|
| 479 |
+
|
| 480 |
async function initiateDownload(fileId) {
|
| 481 |
haptic.impactOccurred('medium');
|
| 482 |
+
const downloadBtn = document.getElementById('modal-download-btn');
|
| 483 |
+
const originalHTML = downloadBtn.innerHTML;
|
| 484 |
+
downloadBtn.innerHTML = '<div class="loading-spinner" style="width:20px; height:20px; border-width:2px;"></div>';
|
| 485 |
+
downloadBtn.onclick = null;
|
| 486 |
+
|
| 487 |
try {
|
| 488 |
const response = await fetch(`{{ url_for('download_tma', file_id='__FILE_ID__') }}`.replace('__FILE_ID__', fileId));
|
| 489 |
const data = await response.json();
|
|
|
|
| 495 |
}
|
| 496 |
} catch (error) {
|
| 497 |
Telegram.WebApp.showAlert('Сетевая ошибка при создании ссылки для скачивания.');
|
| 498 |
+
} finally {
|
| 499 |
+
if (downloadBtn) {
|
| 500 |
+
downloadBtn.innerHTML = originalHTML;
|
| 501 |
+
downloadBtn.onclick = () => { initiateDownload(fileId); };
|
| 502 |
+
}
|
| 503 |
}
|
| 504 |
}
|
| 505 |
|
|
|
|
| 781 |
return jsonify({'status': 'error', 'message': 'Файл не найден или доступ запрещен'}), 404
|
| 782 |
|
| 783 |
token = uuid.uuid4().hex
|
| 784 |
+
cache.set(f"download_token_{token}", file_node, timeout=300)
|
| 785 |
public_url = url_for('public_download', token=token, _external=True)
|
| 786 |
return jsonify({'status': 'success', 'url': public_url})
|
| 787 |
|
| 788 |
@app.route('/public_download/<token>')
|
| 789 |
def public_download(token):
|
| 790 |
file_node = cache.get(f"download_token_{token}")
|
|
|
|
| 791 |
if not file_node:
|
| 792 |
return Response("Ссылка для скачивания недействительна или истекла.", status=404)
|
| 793 |
|
|
|
|
| 797 |
return Response("Ошибка: Путь к файлу не найден.", status=500)
|
| 798 |
|
| 799 |
try:
|
| 800 |
+
hf_url = f"https://huggingface.co/datasets/{REPO_ID}/resolve/main/{quote(hf_path)}"
|
| 801 |
+
headers = {}
|
| 802 |
+
if HF_TOKEN_READ:
|
| 803 |
+
headers["Authorization"] = f"Bearer {HF_TOKEN_READ}"
|
| 804 |
+
|
| 805 |
+
req = requests.get(hf_url, headers=headers, stream=True, allow_redirects=True)
|
| 806 |
+
req.raise_for_status()
|
| 807 |
+
|
| 808 |
+
encoded_filename = quote(original_filename)
|
| 809 |
+
response_headers = {
|
| 810 |
+
'Content-Type': req.headers.get('Content-Type', 'application/octet-stream'),
|
| 811 |
+
'Content-Disposition': f"attachment; filename*=UTF-8''{encoded_filename}",
|
| 812 |
+
'Content-Length': req.headers.get('Content-Length')
|
| 813 |
+
}
|
| 814 |
+
response_headers = {k: v for k, v in response_headers.items() if v is not None}
|
| 815 |
+
|
| 816 |
+
return Response(stream_with_context(req.iter_content(chunk_size=8192)), headers=response_headers)
|
| 817 |
+
|
| 818 |
+
except requests.exceptions.HTTPError as e:
|
| 819 |
+
if e.response.status_code == 404:
|
| 820 |
+
logging.error(f"File not found on Hugging Face during streaming: {hf_path}")
|
| 821 |
+
return Response("Файл не найден на удаленном хранилище.", status=404)
|
| 822 |
+
else:
|
| 823 |
+
logging.error(f"HTTP error downloading from HF via streaming: {e}")
|
| 824 |
+
return Response(f'Ошибка HTTP при скачивании файла: {e}', status=502)
|
| 825 |
except Exception as e:
|
| 826 |
+
logging.error(f"Error streaming with token {token} from HF: {e}")
|
| 827 |
return Response(f'Ошибка скачивания файла: {e}', status=502)
|
| 828 |
|
| 829 |
@app.route('/batch_download_tma')
|
|
|
|
| 1337 |
return jsonify({'status': 'error', 'message': 'File not found or access denied!'}), 404
|
| 1338 |
|
| 1339 |
token = uuid.uuid4().hex
|
| 1340 |
+
cache.set(f"download_token_{token}", file_node, timeout=300)
|
| 1341 |
public_url = url_for('public_download', token=token, _external=True)
|
| 1342 |
return jsonify({'status': 'success', 'url': public_url})
|
| 1343 |
|