node.jsmernmultermulter-s3typescript-execute

How to use multer to upload images with index?


I am creating a product with its variants. Variant is e.g a Shirt can has a variant of Blue color and XL size. So I need to upload its variants along with their images. If I send body like variants : File[], then how will I identify which variants has which images.

I want to do something like

product_variants[0][quantity]:5
product_variants[0][product_variant_attributes][0][variant]:2
product_variants[0][product_variant_attributes][1][variant]:10
product_variants[1][quantity]:10
product_variants[1][product_variant_attributes][0][variant]:6
product_variants[1][product_variant_attributes][1][variant]:13
**variant_images[0] : File
variant_images[1] : File**

If I try it with multer like this:

ProductRouter.route('/')
  .get(getProducts)
  .post(
    authMiddleware,
    restrictTo(['admin']),
    fileMemoryInterceptor.fields([
      {
        name: 'image',
        maxCount: 1,
      },
      {
        name: 'variant_images',
        maxCount: 10,
      },
    ]),
    validateBody(CreateProductDto, true),
    createProduct,
  );

I gets Error :

err MulterError: Unexpected field
    at wrappedFileFilter (D:\Projects\MERN\e-reader\api\node_modules\multer\index.js:40:19)
    at Multipart.<anonymous> (D:\Projects\MERN\e-reader\api\node_modules\multer\lib\make-middleware.js:107:7)
    at Multipart.emit (node:events:514:28)
    at Multipart.emit (node:domain:488:12)
    at HeaderParser.cb (D:\Projects\MERN\e-reader\api\node_modules\busboy\lib\types\multipart.js:358:14)
    at HeaderParser.push (D:\Projects\MERN\e-reader\api\node_modules\busboy\lib\types\multipart.js:162:20)
    at SBMH.ssCb [as _cb] (D:\Projects\MERN\e-reader\api\node_modules\busboy\lib\types\multipart.js:394:37)
    at feed (D:\Projects\MERN\e-reader\api\node_modules\streamsearch\lib\sbmh.js:219:14)
    at SBMH.push (D:\Projects\MERN\e-reader\api\node_modules\streamsearch\lib\sbmh.js:104:16)
    at Multipart._write (D:\Projects\MERN\e-reader\api\node_modules\busboy\lib\types\multipart.js:567:19) {
  code: 'LIMIT_UNEXPECTED_FILE',
  field: 'variant_images[0]',
  storageErrors: []
}

Please help me how to do this ?

I tried using the solution I explained but it failed


Solution

  • You could change your request, for example, use custom filename to connect product data with product files.

    Here's a pseudo code that should roughly demonstrate the idea:

    // client
    // link file and file data via filename map
    
    const formData = new FormData();
    
    products.forEach((product, i) => {
    
        // create custom filename which will serve to connect product data and product file
        const fileNameMap = 'file-' + i;
    
        // store related data in filename hash to match filename
        formData.append(
            fileNameMap,
            // store file related data
            JSON.stringify({
                filename: product.file.filename, // real filename here
                data: {
                    quantity: product.quantity,
                    product_variant_attributes: product.variants
                }
            })
        );
    
        // get associated file, but use fileNameHash
        formData.append('variant_images',
            product.file,
            fileNameMap
        );
    
    });
    
    // backend
    // get the associated data by filename
    
    req.files.variant_images.forEach(file => {
        console.log('file data', JSON.parse(req.body[file.filename]));
    });