Search code examples
expresspostmanmulter

How do I set express multer to accept images from nested fields and test it in postman?


I am expecting product data and variation images from the front end to be something this.

type Product = {
    name: string
    price: number
    discount: number
    discountType: '%' | '₹'
    subCategoryId: number
    description: string
    image: string
    brandId: number
    categoryId: number
    status: 'Active' | 'Inactive'
    hsnCode: string
    variations: Array<{
        variationValueIds: Array<number> // [233, 344]
        productVariationName: string
        price: number
        availableQty: number
        sku: string
        variationImages: Array<any>
    }>
}

I have setup multer to accept variationImages.

productRoutesV2.post('/add-products', upload.fields([{ name: 'variationImages' }]), productController.addProductV2)

I am unable to figure how should I test this in Postman. Also, how will I know which variationImages belongs to which variations index?

I tried making a request from postman that looked something like this postman request


Solution

  • The OP seems to have two questions as :

    1. How to set express multer to accept images from an array of array of images or nested fields ?
    2. How to test the same in postman ?

    The following post is trying to address the first part. The second part will be updated as soon as possible.

    Multer to accept images from an array of array of files:

    point 1: The files must be added to form object as below. This is in the client code.

    // variation images
    product1.variations.forEach((v) => {
      v.variationImages.forEach((img, i) => {
        formdata.append(`${img.path}`, img);
      });
    });
    

    point 2 : Multer any option is to be used to accept all files as below.

    app.post('/upload', upload.any(), (req, res) => {
      res.send('files uploaded');
    });
    

    point 3 : By default Multer changes uploaded file names, the following code would keep the original file name.

        const storage = multer.diskStorage({
         ...,
          filename: function (req, file, cb) {
            cb(null, file.originalname);
          },
        });
    

    Full listing of Nodejs client code.

    const fs = require('fs');
    const axios = require('axios');
    const FormData = require('form-data');
    
    const formdata = new FormData();
    
    const product1 = {
      name: 'product1',
      variations: [
        {
          productVariationName: 'Variation-1',
          variationImages: [
            fs.createReadStream('./var1-img1.jpg'),
            fs.createReadStream('./var1-img2.jpg'),
          ],
        },
        {
          productVariationName: 'Variation-2',
          variationImages: [
            fs.createReadStream('./var2-img1.jpg'),
            fs.createReadStream('./var2-img2.jpg'),
          ],
        },
      ],
    };
    
    // product info.
    formdata.append('product1', JSON.stringify(product1));
    
    // variation images
    product1.variations.forEach((v) => {
      v.variationImages.forEach((img, i) => {
        formdata.append(`${img.path}`, img);
      });
    });
    
    axios
      .post('http://localhost:3000/upload', formdata)
      .then((data) => {
        console.log(data.data);
      })
      .catch((error) => {
        console.log(error);
      });
    

    Full listing of Nodejs server code.

    const express = require('express');
    const multer = require('multer');
    
    const app = express();
    
    const storage = multer.diskStorage({
      destination: function (req, file, cb) {
        cb(null, './uploads');
      },
      filename: function (req, file, cb) {
        cb(null, file.originalname);
      },
    });
    
    const upload = multer({
      storage: storage,
    });
    
    app.post('/upload', upload.any(), (req, res) => {
      console.log(JSON.parse(req.body.product1));
      res.send('files uploaded');
    });
    
    app.listen(3000, () => console.log('L@3000'));
    

    Testing:

    node server.js
    node client.js
    
    input: 
    //hard coded in client.js:
    const product1 = {
      name: 'product1',
      variations: [
        {
          productVariationName: 'Variation-1',
          variationImages: [
            fs.createReadStream('./var1-img1.jpg'),
            fs.createReadStream('./var1-img2.jpg'),
          ],
        },
        {
          productVariationName: 'Variation-2',
          variationImages: [
            fs.createReadStream('./var2-img1.jpg'),
            fs.createReadStream('./var2-img2.jpg'),
          ],
        },
      ],
    };
    
    output:
    // upload folder in the server received the following files
    
    var1-img1.jpg
    var1-img2.jpg
    var2-img1.jpg
    var2-img2.jpg
    
    // server console shows the product object
    {
      name: 'product1',
      variations: [
        { productVariationName: 'Variation-1', variationImages: [Array] },
        { productVariationName: 'Variation-2', variationImages: [Array] }
      ]
    }
    

    Citations:

    1. Uploading a file and passing a additional parameter with multer
    2. FormData: append() method