fixes file handling.

This commit is contained in:
Michael Beck
2025-02-06 00:49:41 +01:00
parent 587bed201e
commit dfe305272c
4 changed files with 91 additions and 13 deletions

1
.gitignore vendored
View File

@@ -195,4 +195,5 @@ cython_debug/
# Exclude data files # Exclude data files
*.csv *.csv
*.zip
config.ini config.ini

64
app.py
View File

@@ -15,6 +15,11 @@ from datetime import datetime
from flask import send_from_directory from flask import send_from_directory
import configparser import configparser
import zipfile
import os
from datetime import timedelta
app = Flask(__name__) app = Flask(__name__)
# Load configuration # Load configuration
@@ -53,6 +58,26 @@ logger.addHandler(queue_handler)
scraping_active = False scraping_active = False
scraping_thread = None scraping_thread = None
def create_zip(file_paths, zip_name):
zip_path = os.path.join(app.root_path, 'temp', zip_name)
with zipfile.ZipFile(zip_path, 'w') as zipf:
for file_path in file_paths:
arcname = os.path.basename(file_path)
zipf.write(file_path, arcname)
return zip_path
def delete_old_zips():
temp_dir = os.path.join(app.root_path, 'temp')
now = datetime.now()
for filename in os.listdir(temp_dir):
if filename.endswith('.zip'):
file_path = os.path.join(temp_dir, filename)
file_time = datetime.fromtimestamp(os.path.getmtime(file_path))
if now - file_time > timedelta(hours=1):
os.remove(file_path)
logger.info(f"Deleted old zip file: {filename}")
def fetch_faction_data(faction_id): def fetch_faction_data(faction_id):
url = f"https://api.torn.com/faction/{faction_id}?selections=&key={API_KEY}" url = f"https://api.torn.com/faction/{faction_id}?selections=&key={API_KEY}"
response = requests.get(url) response = requests.get(url)
@@ -282,15 +307,48 @@ def download_results():
return render_template('download_results.html', files=files) return render_template('download_results.html', files=files)
@app.route('/download_files', methods=['POST'])
def download_files():
delete_old_zips() # Clean up old zip files
file_paths = request.json.get('file_paths', [])
if not file_paths:
return jsonify({"error": "No files specified"}), 400
# Validate and correct file paths
valid_file_paths = []
for file_path in file_paths:
if file_path.startswith('/data/'):
corrected_path = file_path.lstrip('/')
full_path = os.path.join(app.root_path, corrected_path)
if os.path.isfile(full_path):
valid_file_paths.append(full_path)
elif file_path.startswith('/log/'):
corrected_path = file_path.lstrip('/')
full_path = os.path.join(app.root_path, corrected_path)
if os.path.isfile(full_path):
valid_file_paths.append(full_path)
if not valid_file_paths:
return jsonify({"error": "No valid files specified"}), 400
# Create a unique zip file name
zip_name = f"files_{datetime.now().strftime('%Y%m%d%H%M%S')}.zip"
zip_path = create_zip(valid_file_paths, zip_name)
return send_from_directory(directory='temp', path=zip_name, as_attachment=True)
@app.route('/delete_files', methods=['POST']) @app.route('/delete_files', methods=['POST'])
def delete_files(): def delete_files():
file_paths = request.form.getlist('file_paths') file_paths = request.json.get('file_paths', [])
if not file_paths: if not file_paths:
return jsonify({"error": "No files specified"}), 400 return jsonify({"error": "No files specified"}), 400
errors = [] errors = []
for file_path in file_paths: for file_path in file_paths:
file_path = os.path.join(app.root_path, file_path.lstrip('/'))
if not os.path.isfile(file_path): if not os.path.isfile(file_path):
errors.append({"file": file_path, "error": "File not found"}) errors.append({"file": file_path, "error": "File not found"})
continue continue
@@ -323,9 +381,9 @@ def get_size(path):
def download_data_file(filename): def download_data_file(filename):
return send_from_directory('data', filename) return send_from_directory('data', filename)
@app.route('/logs/<path:filename>') @app.route('/log/<path:filename>')
def download_log_file(filename): def download_log_file(filename):
return send_from_directory('logs', filename) return send_from_directory('log', filename)
@app.route('/config/lines_per_page') @app.route('/config/lines_per_page')
def get_lines_per_page(): def get_lines_per_page():

View File

@@ -2,9 +2,9 @@ function deleteFiles(filePaths) {
fetch('/delete_files', { fetch('/delete_files', {
method: 'POST', method: 'POST',
headers: { headers: {
'Content-Type': 'application/x-www-form-urlencoded', 'Content-Type': 'application/json',
}, },
body: new URLSearchParams({ body: JSON.stringify({
'file_paths': filePaths 'file_paths': filePaths
}) })
}) })
@@ -29,18 +29,37 @@ function deleteSelectedFiles() {
} }
} }
function downloadSelectedFiles() { function downloadSelectedFiles() {
const selectedFiles = Array.from(document.querySelectorAll('input[name="fileCheckbox"]:checked')) const selectedFiles = Array.from(document.querySelectorAll('input[name="fileCheckbox"]:checked'))
.map(checkbox => checkbox.value); .map(checkbox => checkbox.value);
if (selectedFiles.length > 0) { if (selectedFiles.length > 0) {
selectedFiles.forEach(file => { fetch('/download_files', {
const link = document.createElement('a'); method: 'POST',
link.href = file; headers: {
link.download = file.split('/').pop(); 'Content-Type': 'application/json',
document.body.appendChild(link); },
link.click(); body: JSON.stringify({ 'file_paths': selectedFiles })
document.body.removeChild(link); })
}); .then(response => {
if (!response.ok) {
return response.json().then(err => { throw new Error(err.error); });
}
return response.blob();
})
.then(blob => {
if (blob.type !== 'application/zip') {
throw new Error("Received invalid ZIP file.");
}
const url = window.URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = 'files.zip';
document.body.appendChild(a);
a.click();
a.remove();
})
.catch(error => alert('Error: ' + error.message));
} else { } else {
alert('No files selected'); alert('No files selected');
} }

0
temp/.gitkeep Normal file
View File