javascriptpythonreactjsflaskreact-fullstack

Axios error when doing a POST request of a .txt file


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:

enter image description here

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 :)


Solution

  • 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.