response from nodejs does not match the result of the ajax request using formidable

2

Hi, I'm uploading a file to nodejs with the formidable module and everything is fine, the file is saved in the directory I have indicated and such, but the response I receive on the page tells me that has not been found no file to upload but if you upload, then I leave the code:

Node function that uploads the file

router.post('/uploadImage', (request, response) => {
    const form = new formidable.IncomingForm()
    const address = path.dirname(__filename).split('/')
    address.pop()

    form.uploadDir = 'BACKEND/imagenes/'; //path donde guardaras la imagines
    form.keepExtensions = true; //mantener las extensiones
    form.maxFieldsSize = 10 * 1024 * 1024; //10MB
    form.multiples = true; //multiples archivos

    form.parse(request, (err, fields, files) => {
        if (err) {
            response.json({
                message: 'error al subir la imagen',
                data: []
            })
        }

        const { upload } = files //Hacemos Destructuring, por lo que equivale a 'const upload = files.upload'
        let data

        if (upload) { //Si existe archivo subido o no
            let filesPath

            if (Array.isArray(upload)) { //Si se han subido mas de un archivo, es decir, si es un Array de archivos
                filesPath = upload.map(file => file.path)
            } else {
                filesPath = upload.path
            }

            data = {
                message: 'imagen subida correctamente !!',
                data: filesPath, //Devolvemos una o la lista de rutas de los archivos
                numImagenes: upload.length //Devolvemos la cantidad de archivos
            }
        } else {
            data = {
                message: 'No hay ninguna imagen seleccionada para subir .. ',
                data: [],
                numImagenes: 0
            }
        }

        response.json(data)
    })
})

Angular test form

  <div class="pruebaSubirArchivo"  style="border: solid">
    <form #formImage="ngForm" action="" enctype="multipart/form-data"  method="POST" ngForm>


      <div>
        <input  type="file" placeholder="imagencita"  (change)="onFileSelected($event)"
        name="imagencita">
      </div>


      <div>
        <button mat-raised-button color="primary" > Enviar Imagen</button>
      </div>

    </form>
  </div>

Frontend Typescript function that uploads image

 onFileSelected(event) {
    this.selectedFile = <File>event.target.files[0];
    //console.log(this.selectedFile);

    //this.empleado_nuevo.imagen_perfil = this.selectedFile.name;
    const fd = new FormData();
    let url = 'http://localhost:3000/uploadImage';

    fd.append('image', this.selectedFile, this.selectedFile.name);
    this.http.post(url, fd).subscribe(
      res => {
        console.log(res);
      });

    //console.log(this.empleado_nuevo.imagen_perfil);
  }

Browser Console (Chrome)

    {message: "No hay ninguna imagen seleccionada para subir .. ", data: Array(0), numImagenes: 0}
data: []
message: "No hay ninguna imagen seleccionada para subir .. "
numImagenes: 0
__proto__: Object

I reiterate that it works only that I do not receive the appropriate response in the explored

    
asked by jose angel 17.12.2018 в 11:45
source

1 answer

2

Initial Response (Erroneous)

You are saying that your form should be processed as multiple, that is, you can receive many files

     form.multiples = true; //multiples archivos

According to the documentation:

  

If this option is enabled, when you call form.parse , the files   argument will contain arrays of files for inputs which submit multiple   files using the HTML5 multiple attribute.

This means that files is not an object but an array of objects of type file and in addition

  const {upload} = files;

It is the deconstruction of an array, which does not have property upload .

Corrected Answer

Testing it in my local, effectively as the OP wrote the files are inside a property. If this property were upload then

  const {upload} = files;

It would be correct and can be an object of type File or an array of these.

However, the property name upload is not fixed. It is determined by the name of the input. So if the OP put:

 <input type="file" name="imagencita">

Files are in files.imagencita

And therefore, when doing the check

 if (upload) {
    ...
 } else {
    // no hay archivos para subir
 }

Effectively there is no property upload .

Doing the full flow for this case:

Since we know that the field is called imagencita , the route would look something like this:

router.post('/uploadImage', (req, res) => {
    const form = new formidable.IncomingForm();
    /* configuracion de form */

    form.uploadDir = path.resolve('${__dirname}/../imagenes/'); //path donde guardaras la img
    form.keepExtensions = true; //mantener las extensiones
    form.maxFieldsSize = 10 * 1024 * 1024; //10MB
    form.multiples = true; //multiples archivos

    form.parse(req, (err, fields, files) => {
        let data, filesPath, numImagenes;
        if (err) {
            data = {
                message: err.message
            };
        } else if (!files || !files.imagencita) {
            data = {
                message: 'No hay ninguna imagen seleccionada para subir .. ',
                data: [],
                numImagenes: 0
            };
        } else {
            const {imagencita} = files;

            if (Array.isArray(imagencita)) {
                //Si se han subido mas de un archivo, es decir, si es un Array de archivos
                numImagenes = imagencita.length;
                filesPath = imagencita.map(file => file.path);
            } else {
                numImagenes = 1;
                filesPath = imagencita.path;
            }

            data = {
                message: 'imagen subida correctamente !!',
                data: filesPath, //Devolvemos una o la lista de rutas de los archivos
                numImagenes //Devolvemos la cantidad de archivos
            };
        }

        res.json(data);
    });
});

If you notice, I took a "fail early" approach to avoid nesting ifs:

  • If there is an error, the response is the error message
  • If there is no error but there are no files or files you do not have the property imagencita the answer is that there are no files uploaded
  • After the previous two, it means that there are files
  • answered by 17.12.2018 / 12:52
    source