这是我的第一个问题。如果我做错了什么请原谅。
设置: 我有一个create-react-app,它使用react-router-dom进行路由。主要思想是某种简单的文件服务器。因此用户可以在网页上上传/删除文件。这将被上传到服务器,然后应在页面上列出。为此,服务器提供了一个 api 端点,其中列出了所有已上传的文件。
因为我想使用某种 dropzone,它直接为我提供 File 对象。我最终不会有表格。所以我认为对于这种情况我必须选择
useFetcher()
然后运行 fetcher.submit(...)
。
问题: 我的问题是,该文件没有发送到服务器。然后我试图寻找它的来源。 我认为它发生在带有注释的两行之间(9 和 27)。因此,包装在 FormData 中的文件在传递给其他函数时会被字符串化为仅名称。
我尝试过的 正如已经提到的,我检查了问题发生在哪一步。所以在我看来,它发生在库内部的某个地方,即将 formData“提交”到
action
函数。所以我查看了库内部,在节点模块(react-router-dom:^6.10.0)的文件dist/index.js
中,在第709行中我找到了一个can转换表单数据的函数:getFormSubmissionInfo
。但我认为因为我的输入是 FormData 类型,所以它不会以与赋予函数相同的方式被触摸和返回。 (参见第 161 行,dist/index.js
)。
问题
useFetcher
是“在后台”向服务器提交文件的正确方法吗,因此无需提交表单?
如果是这样,我如何将文件提供给我的操作函数?
代码片段: 为了将问题与我的项目分开,我创建了问题的 github 存储库 (https://github.com/fabalexsie/StackOverflow_SendFileWithReactRouterDomAction)。
加载器和操作函数在路由对象中引用。
export async function loader() {
return fetch('http://localhost:8080/fileList').then(r => r.json())
}
export async function action({request}) {
const formData = await request.formData();
console.log("Formdata in action", formData) // here the file is only the name
await fetch('http://localhost:8080/upload', {
method: 'POST',
body: formData
});
return {success: true};
}
export function Details() {
const fileList = useLoaderData();
const fetcher = useFetcher();
const handleUpload = (ev) => {
const file = ev.target.files[0];
console.log("File from handle upload", file);
const formData = new FormData();
formData.append('file', file);
formData.append('pw', "InRealityComesFromSomeOtherInput");
console.log("Formdata in handle upload", formData); // here the file is the file object
fetcher.submit(formData, {method: 'POST', action: '/details'})
}
return (
<>
<ul>
{fileList.map(f =>
<li key={f}>
<a href={`http://localhost:8080/files/${f}`}>{f}</a>
</li>
)}
</ul>
<input type="file" id="file" name="file" onChange={handleUpload} />
</>
);
}
休息了一会,我又查看了一下,发现了错误。
提交时,必须指定编码类型“multipart/form-data”,以便以 POST 请求发送文件:
fetcher.submit(formData, {method: 'POST', action: '/details', encType: 'multipart/form-data'})
PS:我也在repo中发布了解决方案。