最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Can i get multer to parse an array of strings in formdata as an array, and not as a comma seperated string? - Stack

programmeradmin2浏览0评论

I am using axios to send a FormData object, containing a categories field, an array of strings, to an express server. I am using multer to parse the FormData recieved, however req.body.categories is a single string after parsing eg 'cat1, cat2, cat3', not an array of strings eg ['cat1', 'cat2', 'cat3']

This is the code i am using to send the FormData:

newProduct: {categories: string[]}

const formData = new FormData()

for (let key of Object.keys(newProduct)){
  formData.append(key, newProduct[key])
}

const response = await axios.post('/api/products', formData)

I have tried to JSON.stringify(categories) before appending this to the formdata but multer understandably just parsed this as a string aswell.

It feels 'icky' to just use categories.split('') after multer has parsed the rest of the formdata so graciously for me, but is there another way or am i doing something wrong?

I am using axios to send a FormData object, containing a categories field, an array of strings, to an express server. I am using multer to parse the FormData recieved, however req.body.categories is a single string after parsing eg 'cat1, cat2, cat3', not an array of strings eg ['cat1', 'cat2', 'cat3']

This is the code i am using to send the FormData:

newProduct: {categories: string[]}

const formData = new FormData()

for (let key of Object.keys(newProduct)){
  formData.append(key, newProduct[key])
}

const response = await axios.post('/api/products', formData)

I have tried to JSON.stringify(categories) before appending this to the formdata but multer understandably just parsed this as a string aswell.

It feels 'icky' to just use categories.split('') after multer has parsed the rest of the formdata so graciously for me, but is there another way or am i doing something wrong?

Share Improve this question edited Mar 28 at 11:36 Lewis Burgess asked Mar 28 at 11:33 Lewis BurgessLewis Burgess 112 bronze badges 1
  • This question is similar to: Can I append an array to 'formdata' in javascript?. If you believe it’s different, please edit the question, make it clear how it’s different and/or how the answers on that question are not helpful for your problem. – traynor Commented Mar 31 at 8:01
Add a comment  | 

2 Answers 2

Reset to default 3

To send arrays, you need to append each value individually using the same key.

const formData = new FormData()

for (const [key, value] of Object.entries(newProduct)){
  if (Array.isArray(value)) {
    for (const arrayItem of value) {
      formData.append(key, arrayItem);
    }
  } else {
    formData.append(key, value);
  }
}

On the server, request.body.categories will either be a string, if there is only one category, undefined if there are zero categories, or an array of strings, if there are multiple categories. It is easiest to check if it is an array, and if not, to turn it into one.

app.post('/api/products', multer().none(), (request, response) => {
  const {body} = request;
  const categories = Array.isArray(body.categories)
      // >= 2 items
    ? body.categories
    : body.categories === undefined
        // 0 items
      ? []
        // 1 item
      : [body.categories];
});

Unfortunately, there is no array type with multipart/form-data. It will only be an array if a key has multiple values. That is why you need code to turn it into an array when there aren't multiple values. Furthermore, you need to handle the case where there are zero categories. With multer, you can check with request.body.categories === undefined and handle such cases as empty arrays.

If you're curious to see this in action, I have created a minimal Express app to test my answer. (You can't run this snippet, but only snippets can be hidden)

import express from 'express';
import multer from 'multer';

const app = express();

app.get('/', (_request, response) => {
  response.send(`<!doctype html>
    <script src="https://cdnjs.cloudflare/ajax/libs/axios/1.8.4/axios.min.js" integrity="sha512-2A1+/TAny5loNGk3RBbk11FwoKXYOMfAK6R7r4CpQH7Luz4pezqEGcfphoNzB7SM4dixUoJsKkBsB6kg+dNE2g==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>

    <script type="module">
        async function sendProduct(product) {
            const formData = new FormData()

            for (let [key, value] of Object.entries(product)){
                if (Array.isArray(value)) {
                    for (const item of value) {
                        formData.append(key, item);
                    }
                } else {
                    formData.append(key, value);
                }
            }

            const response = await axios.post('/api/products', formData);
        }

        await sendProduct({categories: []});
        await sendProduct({categories: ['abc']});
        await sendProduct({categories: ['abc', 'def']});
    </script>
`)
});

app.post('/api/products', multer().none(), (request, response) => {
  const {body} = request;
  console.log(body);
  const categories = Array.isArray(body.categories)
      // >= 2 items
    ? body.categories
    : body.categories === undefined
        // 0 items
      ? []
        // 1 item
      : [body.categories];
  console.log(categories);
  response.send(body);
});

app.listen(3031, () => {
  console.log('listening on http://localhost:3031');
});

I would just use the built-in WHATWG Request.formData() available in node, deno, or bun together with JSON.parse() on the server and with JSON.stringify(), as you tried, on the client. Here's an example you can run in the browser, which can be used on the server:

(async () => {
  let fd = new FormData();
  fd.append("arr", JSON.stringify(['cat1', 'cat2', 'cat3']));
  await new Response(fd).text()
    .then((body) => {
      console.log(body);
      const boundary = body.slice(2, body.indexOf("\r\n"));
      return new Response(body, {
          headers: {
            "Content-Type": `multipart/form-data; boundary=${boundary}`,
          },
        })
        // What you do in the server
        .formData()
        .then((data) => {
          // Here's your Array 
          console.log(JSON.parse(data.get("arr")));
          return data;
        }).catch((e) => {
          throw e;
        });
    }).catch(console.warn);
})().catch(console.warn);

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论