Fix finalize_upload to always return JSON responses

- Improved FileLike class with proper file handling and close() method
- Added better error handling and validation for JSON input
- Added try/finally block to ensure file handles are closed
- Added detailed error logging with traceback for debugging
- Ensures server always returns JSON instead of HTML error pages
parent f1ea5952
...@@ -950,6 +950,9 @@ def finalize_upload(): ...@@ -950,6 +950,9 @@ def finalize_upload():
"""Finalize chunked upload""" """Finalize chunked upload"""
try: try:
data = request.get_json() data = request.get_json()
if not data:
return jsonify({'success': False, 'error': 'Invalid JSON data'}), 400
upload_id = data.get('uploadId') upload_id = data.get('uploadId')
file_name = data.get('fileName') file_name = data.get('fileName')
match_id = data.get('matchId') match_id = data.get('matchId')
...@@ -990,115 +993,124 @@ def finalize_upload(): ...@@ -990,115 +993,124 @@ def finalize_upload():
self.filename = filename self.filename = filename
self.name = filename self.name = filename
self.content_type = 'application/zip' # Default for ZIP files self.content_type = 'application/zip' # Default for ZIP files
self._file = None self._closed = False
self._pos = 0
def __enter__(self):
self._file = open(self.path, 'rb')
return self
def __exit__(self, exc_type, exc_val, exc_tb):
if self._file:
self._file.close()
def read(self, size=-1): def read(self, size=-1):
if self._file is None: if self._closed:
raise ValueError("I/O operation on closed file")
if not hasattr(self, '_file'):
self._file = open(self.path, 'rb') self._file = open(self.path, 'rb')
if size == -1: if size == -1:
data = self._file.read() data = self._file.read()
else: else:
data = self._file.read(size) data = self._file.read(size)
self._pos += len(data)
return data return data
def seek(self, pos, whence=0): def seek(self, pos, whence=0):
if self._file is None: if self._closed:
raise ValueError("I/O operation on closed file")
if not hasattr(self, '_file'):
self._file = open(self.path, 'rb') self._file = open(self.path, 'rb')
self._file.seek(pos, whence) self._file.seek(pos, whence)
self._pos = self._file.tell()
def tell(self): def tell(self):
if self._file is None: if self._closed:
raise ValueError("I/O operation on closed file")
if not hasattr(self, '_file'):
self._file = open(self.path, 'rb') self._file = open(self.path, 'rb')
return self._file.tell() return self._file.tell()
def close(self):
if hasattr(self, '_file') and self._file:
self._file.close()
self._closed = True
def save(self, dst): def save(self, dst):
if self._closed:
raise ValueError("I/O operation on closed file")
shutil.move(self.path, dst) shutil.move(self.path, dst)
mock_file = FileLike(final_path, file_name) mock_file = FileLike(final_path, file_name)
if match_id: try:
# ZIP upload for match if match_id:
from app.models import Match # ZIP upload for match
match = Match.query.get_or_404(int(match_id)) from app.models import Match
match = Match.query.get_or_404(int(match_id))
# Check permissions # Check permissions
if not current_user.is_admin and match.created_by != current_user.id: if not current_user.is_admin and match.created_by != current_user.id:
return jsonify({'success': False, 'error': 'Permission denied'}), 403 return jsonify({'success': False, 'error': 'Permission denied'}), 403
# Update match status # Update match status
match.zip_upload_status = 'uploading' match.zip_upload_status = 'uploading'
db.session.commit() db.session.commit()
upload_record, error_message = file_handler.process_upload( upload_record, error_message = file_handler.process_upload(
mock_file, 'zip', current_user.id, int(match_id) mock_file, 'zip', current_user.id, int(match_id)
) )
if error_message: if error_message:
match.zip_upload_status = 'failed' match.zip_upload_status = 'failed'
db.session.commit()
return jsonify({'success': False, 'error': error_message}), 400
match.zip_filename = upload_record.filename
match.zip_sha1sum = upload_record.sha1sum
match.zip_upload_status = 'completed'
match.zip_upload_progress = 100.00
match.set_active()
db.session.commit() db.session.commit()
return jsonify({'success': False, 'error': error_message}), 400
match.zip_filename = upload_record.filename # Clean up temp files
match.zip_sha1sum = upload_record.sha1sum shutil.rmtree(temp_dir)
match.zip_upload_status = 'completed'
match.zip_upload_progress = 100.00
match.set_active()
db.session.commit()
# Clean up temp files flash(f'ZIP file uploaded successfully for Match #{match.match_number}! Match is now active.', 'success')
shutil.rmtree(temp_dir) return jsonify({
'success': True,
'redirect': url_for('main.fixture_detail', fixture_id=match.fixture_id)
}), 200
flash(f'ZIP file uploaded successfully for Match #{match.match_number}! Match is now active.', 'success') else:
return jsonify({ # Fixture upload
'success': True, upload_record, error_message = file_handler.process_upload(
'redirect': url_for('main.fixture_detail', fixture_id=match.fixture_id) mock_file, 'fixture', current_user.id
}), 200 )
else: if error_message:
# Fixture upload return jsonify({'success': False, 'error': error_message}), 400
upload_record, error_message = file_handler.process_upload(
mock_file, 'fixture', current_user.id
)
if error_message: # Parse fixture
return jsonify({'success': False, 'error': error_message}), 400 fixture_parser = get_fixture_parser()
success, parse_error, parsed_matches = fixture_parser.parse_fixture_file(
upload_record.file_path, upload_record.original_filename, current_user.id
)
# Parse fixture if not success:
fixture_parser = get_fixture_parser() return jsonify({'success': False, 'error': parse_error}), 400
success, parse_error, parsed_matches = fixture_parser.parse_fixture_file(
upload_record.file_path, upload_record.original_filename, current_user.id
)
if not success: success, save_error, match_ids = fixture_parser.save_matches_to_database(
return jsonify({'success': False, 'error': parse_error}), 400 parsed_matches, upload_record.sha1sum
)
success, save_error, match_ids = fixture_parser.save_matches_to_database( if not success:
parsed_matches, upload_record.sha1sum return jsonify({'success': False, 'error': save_error}), 500
)
if not success: # Clean up temp files
return jsonify({'success': False, 'error': save_error}), 500 shutil.rmtree(temp_dir)
# Clean up temp files flash(f'Successfully uploaded and parsed {len(match_ids)} matches!', 'success')
shutil.rmtree(temp_dir) return jsonify({
'success': True,
'redirect': url_for('main.matches')
}), 200
flash(f'Successfully uploaded and parsed {len(match_ids)} matches!', 'success') finally:
return jsonify({ # Ensure file is closed
'success': True, mock_file.close()
'redirect': url_for('main.matches')
}), 200
except Exception as e: except Exception as e:
logger.error(f"Finalize upload error: {str(e)}") logger.error(f"Finalize upload error: {str(e)}")
return jsonify({'success': False, 'error': str(e)}), 500 import traceback
\ No newline at end of file logger.error(f"Traceback: {traceback.format_exc()}")
return jsonify({'success': False, 'error': f'Upload finalization failed: {str(e)}'}), 500
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment