I am working on a project with Flask and React and more specifically, right now I am working on an API endpoint that has the utility of receiving a .txt file from the frontend, and then it would run a script that analyzes data from that .txt and saves plots related to the analysis.
Here is the API endpoint at the backend:
@analysis_ns.route('/upload', methods=["POST", "GET"])
class ChatAnalysisUploadResource(Resource):
def get(self):
return {"message": "This endpoint is only for file uploads via POST."}, 405
#@jwt_required()
def post(self):
"""Upload a chat file, process it and return the image URLs"""
try:
if 'file' not in request.files:
abort(400, description="No file part")
file = request.files['file']
if file.filename == '':
abort(400, description="No selected file")
if file and allowed_file(file.filename):
filename = secure_filename(file.filename)
file_path = os.path.join(UPLOAD_FOLDER, filename)
file.save(file_path)
# Procesa el archivo y genera las imágenes
process_chat_file(file_path)
image_paths = ['static/mensajes_enviados.png', 'static/emojis.png']
missing_images = [path for path in image_paths if not os.path.exists(path)]
if missing_images:
abort(500, description=f"Imagen no encontrada: {missing_images}")
image_urls = {
'urls': [
url_for('static', filename='mensajes_enviados.png', _external=True),
url_for('static', filename='emojis.png', _external=True)
]
}
# Guardar los resultados en la base de datos
result_summary = ";".join(image_urls['urls'])
new_analysis = ChatAnalysisResults(
chat_name=filename,
result_summary=result_summary
)
new_analysis.save()
return jsonify(image_urls), 200
abort(400, description="File type not allowed")
# Captura el error y devuelve un mensaje serializable
except Exception as e:
return jsonify({"error": str(e)}), 500
And here is the React component that handle the upload of the document (I am not very good at react):
import { useState } from 'react'
import PropTypes from 'prop-types'
import axios from 'axios'
import '../App.css'
function UploadForm({ setImages }) {
const [file, setFile] = useState(null);
const [response, setResponse] = useState('');
const [loading, setLoading] = useState(false);
const handleFileChange = (event) => {
setFile(event.target.files[0]);
};
const handleUpload = async () => {
if (!file) {
alert("Please select a chat file to upload.");
return;
}
const formData = new FormData()
formData.append('file', file) // Cambiado de 'chat_file' a 'file'
setLoading(true) // Inicia la animación de carga
setImages([]) // Limpia los resultados anteriores
setResponse('') // Opcional: limpia el mensaje de respuesta
console.log('Loading started');
try {
const response = await axios.post('http://127.0.0.1:8080/analysis/upload', formData, {
headers: {
'Content-Type': 'multipart/form-data'
}
});
console.log('Response data:', response.data);
setImages(response.data.urls);
setResponse('Chat file analyzed successfully');
} catch (error) {
console.error('Error uploading the file:', error);
setResponse('Error uploading the file: ' + (error.response ? error.response.data.error : error.message));
} finally {
setLoading(false); // Detiene la animación de carga independientemente del resultado
console.log('Loading finished');
}
}
return (
<div className="upload-form">
<input type="file" onChange={handleFileChange} accept=".txt" />
<button onClick={handleUpload}>
{loading ? 'Analyzing' : 'Analyze Chat'}
</button>
{response && <p>{response}</p>}
{loading && (
<div className='loading'>
<div className='spinner'></div>
</div>
)}
</div>
)
}
UploadForm.propTypes = {
setImages: PropTypes.func.isRequired,
}
export default UploadForm
And this is the error that I am getting in the console:
Also the error that I can see on the VSCode Terminal is the following:
File "/opt/anaconda3/lib/python3.11/json/encoder.py", line 180, in default
raise TypeError(f'Object of type {o.__class__.__name__} '
TypeError: Object of type Response is not JSON serializable
All the API endpoints so far work correctly except for this one, I have been stuck with this problem for a week and I could use some help. If you need more info or want to see more parts/scripts of the project feel free to ask :)
I can see there is a CORS policy error in your code. It arises because you are working on two different URLs, one for backend and one for frontend, and to resolve it you have to do changes in your flask code. Install flask_cors
package and than import modules from it;
from flask_cors import cross_origin #for specific route
from flask_cors import CORS #for whole app
after importing
analysis_ns = Flask(__name__) #you might have done this in beginning your code
CORS(analysis_ns) #for enabling CORS in whole app, define it at the beginning of your code
#rest of your code
@analysis_ns.route('/upload', methods=["POST", "GET"])
@cross_origin #for enabling CORS in specific route
#rest of your code
This might help to resolve the error. I had the CORS policy issue during my internship where I was working with same technology, that is, Flask and React.