javascriptnode.jsformidable

Why doesn't my formidable code work with node js (upload an image and have the code respond according to the user's action)?


I'm watching bluuweb's node course and in it they do a practical exercise.

This is the code for minute 39 specifically:

const formidable = require("formidable");

const cambiarFotoPerfil = (req, res) => {
    const form = new formidable.IncomingForm();
    form.maxFileSize = 5 * 1024 * 1024;

    form.parse(req, async (err, fields, files) => {

        try {
            
            if (err) {
                throw new Error('Falló formidable')
            }

            console.log(fields);
            console.log(files.myFile)

            const file = files.myFile;

            if(file.originalFilename === ""){
                throw new Error('No se seleccionó ninguna imagen')
            }
            
            if(!['image/jpeg', 'image/png'].includes(file.mimetype)){
                throw new Error('Por favor agrega una imagen con formato .jpg o png')
            }

            if(file.size > 5 * 1024 * 1024){
                throw new Error('La imagen debe ser de máximo 5MB')
            }

            req.flash("mensajes", [{ msg: "Ya se subió la imagen" }]);
            return res.redirect('/perfil');
            
        } catch (error) {
            console.log(error);
            req.flash("mensajes", [{ msg: error.message }]);
            return res.redirect("/perfil");
        }
    });
};

module.exports = {
    formPerfil,
    cambiarFotoPerfil
}

This is the HTML:

<form action="/perfil?_csrf={{csrfToken}}" method="post" enctype="multipart/form-data">
    {{!-- <input type="hidden" name="_csrf" value="{{csrfToken}}" /> --}}
    <input class="form-control form-control-sm mb-2" type="file" id="formFileSm" name="myFile" />
    <button class="btn btn-dark">Cambiar foto</button>
</form>

The problem is that if I don't send any files it jumps to the error 'Failed great' and ignores the rest. And when I send a jpg or png file I get the error Please add an image in .jpg or png format, although it is supposed to comply with the format.

I tried to remove the following code

if (err) {
      throw new Error('Falló formidable')
}

but it jumped to an error

Cannot read properties of undefined (reading 'originalFilename')

I also tried uninstalling formidable and reinstalling it but nothing changed. I don't know if it's a syntax problem or a formidable bug.


Solution

  • Solution to my question

    Finally I found a solution. In const file = files.myFile[0]; I added the [0].

    This is my new script:

    const {formidable} = require("formidable");
    
    const cambiarFotoPerfil = (req, res) => {
    
        const form = formidable({});
        form.maxFileSize = 5 * 1024 * 1024; // 5MB
    
        form.parse(req, async (err, fields, files) => {
            if (err) {
                req.flash("mensajes", [{ msg: "Falló formidable" }]);
                return res.redirect("/perfil");
            }
        
            // HERE the [0] was added as mentioned above
            const file = files.myFile[0];
    
            try {
                // console.log(fields);
                console.log(file)
    
                console.log(file.originalFilename)
    
                if(file.originalFilename === ""){
                    throw new Error('No se seleccionó ninguna imagen')
                }
                
                if(!['image/jpeg', 'image/png'].includes(file.mimetype)){
                    throw new Error('Por favor agrega una imagen con formato .jpg o png')
                }
    
                if(file.size > 5 * 1024 * 1024){
                    throw new Error('La imagen debe ser de máximo 5MB')
                }
    
                req.flash("mensajes", [{ msg: "Ya se subió la imagen" }]);
                return res.redirect('/perfil');
                
            } catch (error) {
                console.log(error);
                req.flash("mensajes", [{ msg: error.message }]);
                return res.redirect("/perfil");
            }
        });
    };