如何在javascript中POST mulitpart/form-data

wbgh16ku  于 2023-05-16  发布在  Java
关注(0)|答案(1)|浏览(220)

在我的前端,我使用input[type ='file']从用户那里获取图像数据,并POST到我的API。在后端,我使用强大的解析数据。问题是uploadImage API返回输入缓冲区包含不支持的图像格式。
注意**->我可以直接从前端上传文件到sanity cdn,但它会在浏览器中暴露我的token,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);
  }
}
fcwjkofz

fcwjkofz1#

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

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

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

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

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>

后端路由看起来像这样-

async function uploadImage(req, res) {
  if (req.method !== "POST") {
    return res.status(405).end() // Method Not Allowed
  }

  const form = new IncomingForm({ multiples: false })

  form.parse(req, async (err, fields, files) => {
    if (err) {
      console.error(err)
      return res.status(500).end() // Internal Server Error
    }

    const { myfile } = files

    if (!myfile) {
      return res.status(400).end() // Bad Request
    }

    try {
      const result = await client.asset.upload("image", myfile, { filename: myfile.name })
      console.log("uploaded image:", result.asset._id)
      return res.status(200).json({ fileId: result.asset._id })
    } catch (error) {
      console.error(error)
      return res.status(500).end() // Internal Server Error
    }
  })
}

相关问题