fixes file handling.
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -195,4 +195,5 @@ cython_debug/
|
|||||||
|
|
||||||
# Exclude data files
|
# Exclude data files
|
||||||
*.csv
|
*.csv
|
||||||
|
*.zip
|
||||||
config.ini
|
config.ini
|
||||||
64
app.py
64
app.py
@@ -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():
|
||||||
|
|||||||
@@ -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
0
temp/.gitkeep
Normal file
Reference in New Issue
Block a user