我有一个通过 Inertia.js 连接到 Laravel 后端的 React 应用程序。 Inertia 提供了上传文件的简单方法: https://www.inertiajs.com/file-uploads
我的代码与此非常相似,但有些东西阻止设置文件。
这是当我通过选择器选择文件时调用的方法:
const { data, setData, post, progress, errors, } = useForm({
recipient: '',
recipient_mail: '',
sum: '',
file: null,
filename: '',
type: '',
})
const handleFileChange = (e) => {
const file = e.target.files[0];
console.log(file); // It's defined here, after selecting a valid file.
if (file && file.type === 'application/pdf') {
setData('file', file);
setData('filename', file.name);
console.log("File attached");
} else {
setFile(null)
setData('file', null);
setData('filename', '');
console.log("No file attached");
}
};
但是,如果我之后发布一些调试信息:
const debugClick = () => {
console.log("data.file:", data.file); // It's always "null"
console.log("data.filename:", data.filename); // This is set correctly
}
虽然所有其他字段(仅字符串和数字)都已正确设置,但文件仍然始终是
null
。
不用说,如果我尝试提交表单,所选文件不会一起发送。似乎 setter 方法由于某种原因失败了。 作为参考,以下是 pdf 文件(或其中一个,因为我尝试过多个文件)如何显示在
console.log
:
File { name: "invoice_dummy.pdf", lastModified: 1725345145845, webkitRelativePath: "", size: 102020, type: "application/pdf" }
create.jsx:24:16
作为替代方案,我尝试使用 React 的
useEffect
,创建一个 FormData
对象并通过 formData.append()
附加文件。在这种情况下,useEffect 的 setter 方法按预期设置文件,但 formData.append
没有添加任何内容。
为了完整起见,这里还有输入字段:
<input type="file"
id="document_pdf"
name="file"
accept=".pdf,application/pdf"
value={data.file}
className="mt-1 block w-full"
onChange={handleFileChange}
/>
我觉得要么我忽略了一些明显的东西,要么有一些关于表单和文件我不知道的东西,而 Inertia.js 文档认为这是理所当然的。
value={data.file}
元素中使用 <input>
。<input
type="file"
id="document_pdf"
name="file"
accept=".pdf,application/pdf"
className="mt-1 block w-full"
onChange={handleFileChange}
/>
使用
Inertia.post()
发送带有 FormData
选项的 forceFormData: true
对象,这会告诉 Inertia 将其视为文件上传。
这是通过 post 请求上传文件的最终代码块:
const { data, setData, post, progress, errors } = useForm({
recipient: '',
recipient_mail: '',
sum: '',
file: null,
filename: '',
type: '',
});
const handleFileChange = (e) => {
const file = e.target.files[0];
console.log(file);
if (file && file.type === 'application/pdf') {
setData('file', file);
setData('filename', file.name);
console.log("File attached");
} else {
setData('file', null);
setData('filename', '');
console.log("No file attached");
}
};
const handleSubmit = (e) => {
e.preventDefault();
const formData = new FormData();
formData.append('recipient', data.recipient);
formData.append('recipient_mail', data.recipient_mail);
formData.append('sum', data.sum);
if (data.file) {
formData.append('file', data.file);
}
// Inertia sends the request as multipart/form-data
Inertia.post('/your-endpoint', formData, {
forceFormData: true,
onSuccess: () => console.log("File submitted successfully"),
onError: (errors) => console.log(errors),
});
};