在我的前端,我使用 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);
}
}
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>