如何在 javascript 中发布多部分/表单数据

问题描述 投票:0回答:1

在我的前端,我使用 input[type='file'] 从用户那里获取图像数据,然后 POST 到我的 API。在后端,我使用 formidable 解析数据。问题是 uploadImage Api 返回的输入缓冲区包含不受支持的图像格式。

注意** -> 我可以直接从前端将文件上传到 sanity cdn,但它会在浏览器中暴露我的令牌,而 sanity 不喜欢它。

前端->

export default function Component() {
  const handleSubmit = async (e: FormEvent<HTMLFormElement>) => {
    e.preventDefault();
    const file = e.currentTarget[0]?.files[0];
    const formdata = new FormData();
    formdata.append("file", file);

    fetch("/api/uploadImage", {
      method: "POST",
      body: formdata,
    })
      .then((res) => res.json())
      .then((r) => console.log(r))
      .catch((err) => console.log(err));
  };

  return (
    <div>
      <form encType="multipart/form-data" onSubmit={handleSubmit}>
        <input type="file" id="inputFile" name="avatar" />
        <button
          type="submit"
          className="rounded-md bg-indigo-500 px-4 py-1 text-white"
        >
          Select some files
        </button>
      </form>
    </div>
  );
}

后端->

export const config = {
  api: {
    bodyParser: false,
  },
};

export default async function handler(
  req: NextApiRequest,
  res: NextApiResponse
) {
  const data = await new Promise((resolve, reject) => {
    const form = formidable();
    form.parse(req, (err, fields, files) => {
      if (err) {
        reject(err);
      }
      resolve({ req, fields, files });
    });
  });
  const { fields, files } = data;

  try {
    const { _id } = await client.assets.upload("image", files);
    res.status(200).json(_id);
  } catch (err) {
    res.status(400).send(err);
  }
}
javascript reactjs next sanity formidable
1个回答
0
投票

FormData 构造函数 已经正确编码文件。您可以极大地简化您的组件 -

function FileUpload() {
  const handleSubmit = (event) => {
    event.preventDefault()
    const formData = new FormData(event.target)
    fetch("/upload", {
      method: "POST",
      body: formData,
    })
    .then((response) => { … })
    .catch((error) => { … });
  };

  return (
    <form onSubmit={handleSubmit}>
      <input
        type="file"
        name="myfile"
        accept=".jpg, .jpeg, .png"
      />
      <button>Upload</button>
    </form>
  )
}

或者试试这个直接在浏览器中显示上传图片的demo -

function App() {
  const [img, setImg] = React.useState(null)
  const handleSubmit = (event) => {
    event.preventDefault()
    const formData = new FormData(event.target)
    const reader = new FileReader()
    reader.onload = (event) => {
      setImg(event.target.result)
    }
    reader.readAsDataURL(formData.get("myfile"))
  };

  return (
    <form onSubmit={handleSubmit}>
      <input
        type="file"
        name="myfile"
        accept=".jpg, .jpeg, .png"
      />
      <button>Upload</button>
      {img && <img src={img} />}
    </form>
  );
}

ReactDOM.createRoot(document.querySelector("#app")).render(<App />)
img { max-width: 100vw; }
<script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
<div id="app"></div>

© www.soinside.com 2019 - 2024. All rights reserved.