formData 无法传递到后端。

huangapple go评论71阅读模式
英文:

formData cannot arrive to backend

问题

我正在尝试创建一个团队部分,它是一个动态表单。您可以根据需要插入团队成员,并包括以下字段:"memberName"(成员姓名)"memberDescription"(成员描述)"memberJobTitle"(成员职务)"images"(图片)

但是,前端似乎出现了问题,某种方式文件未传递到后端。当我提交以创建团队成员时,我收到以下消息:

message: "Cannot read properties of undefined (reading 'path')

然而,

  1. 当我尝试使用Postman上传文件到团队成员时,它可以正常工作。因此,我认为问题不在后端。
team[0][memberName]: "Lala"
team[0][memberJobTitle]: "Lala"
team[0][images][0]: "image.jpg"
team[0][memberDescription]: "Lala"
  1. 在前端,当我提交后,我可以在 console.log(values) 中看到我上传的文件。
team: Array(1)
  0:
    images: Array(1)
      0: FileList {0: File, length: 1}
      length: 1
    memberDescription: "与我们一起工作了5年"
    memberJobTitle: "市场营销"
    memberName: "Jane Doe"
  1. 如果我记录 console.log("append image: ", item.images[0]);,它也会显示给我一个 FileList。
FileList {0: File, length: 1}
  0: File {name: 'real-estate-logo-template_1195-19.jpg.webp', lastModified: 1672667306966, lastModifiedDate: Mon Jan 02 2023 13:48:26 GMT+0000 (Western European Standard Time), webkitRelativePath: '', size: 9894, }
  length: 1

提交处理程序:

const submitHandler = async (values) => {
    const formData = new FormData();

    // 添加其他字段

    values.team = values.team || [{}];

    values.team.forEach((item, index) => {
        formData.append(`team[${index}][memberName]`, item.memberName || "");
        // 添加其他团队字段

        formData.append(`team[${index}][images][0]`, item.images[0]);

        console.log("append image: ", item.images[0]);
    });

    await axios({
        method: "POST",
        url: `http://localhost:8080/api/pages/${pageId}/aditional-section`,
        data: formData,
        headers: {
            "Content-Type": "multipart/form-data",
            Authorization: "Bearer " + localStorage.getItem("token"),
        },
    })
    .then((res) => {
        console.log(res);
    })
    .catch((res) => {
        console.log(res);
    });

    console.log(values);
};

我在使用 Formik 处理表单。

英文:

I'm trying to make a team section, that it is a dynamic form. You can insert team members as much as you want, and it includes, "memberName", "memberDescription", "memberJobTitle", "images".

Really do not understand why but something is wrong in the frontend, somehow file does not arrive to backend, when I submit to create a team member, I got this message:

> message: "Cannot read properties of undefined (reading 'path')

However,

  1. When I try upload file to team member on Postman with form-data, it works. So, I assume problem is not in the backend.

    team[0][memberName]: "Lala"
    team[0][memberJobTitle]: "Lala"
    team[0][images][0]: "image.jpg"
    team[0][memberDescription]: "Lala"

  2. In the frontend, I can see the file that I uploaded when I submit in console.log(values).

    team: Array(1)
    0:
    images:Array(1)
    0: FileList {0: File, length: 1}
    length: 1
    [[Prototype]]: Array(0)
    memberDescription: "work with us 5 years long"
    memberJobTitle: "marketing"
    memberName: "Jane Doe"

  3. If I log console.log("append image: ", item.images[0]); it also shows me a FileList.

    FileList {0: File, length: 1}
    0: File {name: 'real-estate-logo-template_1195-19.jpg.webp', lastModified: 1672667306966, lastModifiedDate: Mon Jan 02 2023 13:48:26 GMT+0000 (Western European Standard Time), webkitRelativePath: '', size: 9894, …}
    length: 1

submitHandler

const submitHandler = async (values) => {
    const formData = new FormData();

    // append other fields

    values.team = values.team || [{}];

    values.team.forEach((item, index) => {
      formData.append(`team[${index}][memberName]`, item.memberName || "");
      //append other team fields

      formData.append(`team[${index}][images][0]`, item.images[0]);

      console.log("append image: ", item.images[0]);
    });


    await axios({
      method: "POST",
      url: `http://localhost:8080/api/pages/${pageId}/aditional-section`,
      data: formData,
      headers: {
        "Content-Type": "multipart/form-data",
        Authorization: "Bearer " + localStorage.getItem("token"),
      },
    })
      .then((res) => {
        console.log(res);
      })
      .catch((res) => {
        console.log(res);
      });

    console.log(values);
  };

I'm using Formik to handle form.

     <FieldArray name="team">
    {({ insert, remove, push }) => (
      <div>
        {values.team.length > 0 &&
          values.team.map((item, index) => (
            <div className="row" key={index}>
              <div className="col">
                <label htmlFor={`team.${index}.images[0]`}>
                  Upload image
                </label>

                {/* <Field
                  name={`team.${index}.images`}
                  type="file"
                /> */}

                <FileInput
                  name={`team.${index}.images[0]`}
                  type="file"
                  value={undefined}
                />

                <ErrorMessage
                  name={`team.${index}.images[0]`}
                  component="div"
                  className="field-error"
                />
              </div>
            </div>
          ))}
        <button
          type="button"
          className="secondary"
          onClick={() =>
            push({
              memberName: "",
              memberJobTitle: "",
              memberDescription: "",
              images: "",
            })
          }
        >
          Add Member
        </button>
      </div>
    )}
</FieldArray>

答案1

得分: 2

"MDN文档"(https://developer.mozilla.org/en-US/docs/Web/API/FormData/append#parameters)中提到:

value

字段的值。可以是字符串或Blob(包括File等子类)。如果没有指定这些内容之一,则该值将被转换为字符串。

似乎不支持FileList类型,但支持File类型。尝试循环遍历FileList并将每个文件附加到formData,如下所示。

const submitHandler = async (values) => {
    ...

    values.team.forEach((item, index) => {
      formData.append(`team[${index}][memberName]`, item.memberName || "");
      //附加其他团队字段
      // 在之前
      // formData.append(`team[${index}][images][0]`, item.images[0]);
      
      // 在之后 - 遍历图像,附加File
      for (let i = 0; i < item.images[0].length; i++) {
         const file = item.images[0].files[i];
         formData.append(`team[${index}][images][0]`, file);
      }

      console.log("附加图像:", item.images[0]);
    });

    ...
  };

这应该可以正常工作,前提是您的后端设置可以接收多个文件。

英文:

MDN Docs states:

> value
>
> The field's value. This can be a string or Blob (including subclasses such as File). If none of these are specified the value is converted to a string.

It appears that the FileList type isn't supported but the File type is. Try looping through the FileList and appending each file to the formData like so.

const submitHandler = async (values) =&gt; {
    ...

    values.team.forEach((item, index) =&gt; {
      formData.append(`team[${index}][memberName]`, item.memberName || &quot;&quot;);
      //append other team fields
      // Before
      // formData.append(`team[${index}][images][0]`, item.images[0]);
      
      // After - Loop through images, and append the File
      for (let i = 0; i &lt; item.images[0].length; i++) {
         const file = item.images[0].files[i];
         formData.append(`team[${index}][images][0]`, file);
      }

      console.log(&quot;append image: &quot;, item.images[0]);
    });


    ...
  };

This should work, granted your backend is set up to receive multiple files.

huangapple
  • 本文由 发表于 2023年1月9日 08:03:56
  • 转载请务必保留本文链接:https://go.coder-hub.com/75052178.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定