Search code examples
javascriptnode.jsangularexpressmulter

Send array of images from Angular to ExpressJS server via POST using multer


I have an Angular form that accepts multiple images and I want to send those to my ExpressJS server with a POST request. I managed to do it for a SINGLE picture with multer and FormData, but I'm struggling to get it done for more than 1 picture.

Here's my server side code:

const storage = multer.memoryStorage();
let upload = multer({storage: storage});


router.post('/uploadPictures', upload.array("pictures", 5), uploadPicture);

The uploadPicture function just displays req.file, req.body & req.files.

Here's my Angular code.

Component:

pictures: any[];

async uploadProperty() {
    if (this.uploadPropertyForm.valid) {
      const formData = new FormData();

      for (let i = 0; i < this.pictures.length; i += 1) {
        formData.set(`pictures[${i}]`, this.pictures[i]);
      }

      this.propertiesService
        .uploadPictures(formData)
        .subscribe((response) => {
          console.log(response);
        });
    }
  }

Service:

uploadPictures(pictures: FormData) {
    const url = `${this.baseUrl}/properties/uploadPictures`;

    return this.http.post(url, pictures);
  }

I tried a few different things to make it work:

  1. Using the method formData.append(). This way req.file is undefined, even for a single image.
  2. Using the for loop in different ways:
    for (let i = 0; i < this.pictures.length; i += 1) {
        formData.set(`pictures[]`, this.pictures[i]);
      }

or

for (let i = 0; i < this.pictures.length; i += 1) {
        formData.append(`pictures[]`, this.pictures[i]);
      }

When I use formData.append(), req.file & req.files is undefined.
When I use formData.set() I get the following multer error:

MulterError: Unexpected field
    at wrappedFileFilter (F:\projectName\node_modules\multer\index.js:40:19)
    at Multipart.<anonymous> (F:\projectName\node_modules\multer\lib\make-middleware.js:107:7)
    at Multipart.emit (node:events:513:28)
    at Multipart.emit (node:domain:489:12)
    at HeaderParser.cb (F:\projectName\node_modules\busboy\lib\types\multipart.js:358:14)
    at HeaderParser.push (F:\projectName\node_modules\busboy\lib\types\multipart.js:162:20)
    at SBMH.ssCb [as _cb] (F:\projectName\node_modules\busboy\lib\types\multipart.js:394:37)
    at feed (F:\projectName\node_modules\streamsearch\lib\sbmh.js:248:10)
    at SBMH.push (F:\projectName\node_modules\streamsearch\lib\sbmh.js:104:16)
    at Multipart._write (F:\projectName\node_modules\busboy\lib\types\multipart.js:567:19)

As you can see the message doesn't provide much information about where or what's causing the problem so I'm kind of lost.

I'm only trying to upload 2 images so size shouldn't be a problem.


Solution

  • You told it to expect the files to be in fields named pictures.

    router.post('/uploadPictures', upload.array("pictures", 5), uploadPicture);
    

    Then you sent it data with files in fields named pictures[0] and pictures[1].

    formData.set(`pictures[${i}]`, this.pictures[i]);
    

    Then you tried to data in data in fields name pictures[].

     formData.append(`pictures[]`, this.pictures[i]);
    

    Multer isn't PHP. Use the name you actually said: pictures with nothing else after it.