如何用react-router-dom的loader/action实现无表单文件POST上传?
React Router useFetcher 提交FormData丢失文件内容问题
这是我的第一个问题,若有不当之处请见谅。
环境配置
- 基于create-react-app搭建项目,使用react-router-dom实现路由
- 目标是实现简易文件服务器:支持网页端上传/拖拽文件,文件上传至服务器后在页面展示,服务器提供API接口列出已上传文件
- 因需要实现可直接获取File对象的拖拽区域,最终不会使用表单,因此选择使用
useFetcher()调用fetcher.submit(...)提交数据
问题
文件无法成功发送至服务器。排查后发现:FormData中携带的文件,在从handleUpload函数传递到action函数的过程中(对应代码注释标记的第9行和第27行之间),被序列化为仅保留文件名,丢失了文件内容。
已尝试操作
- 定位问题环节,怀疑是react-router-dom内部将FormData提交至action函数的过程中出现异常
- 查看了react-router-dom@6.10.0的
dist/index.js文件,找到负责转换FormData的getFormSubmissionInfo函数(第709行),按代码逻辑,当输入为FormData类型时应该原样返回(参考第161行代码),但实际结果不符合预期
疑问
useFetcher是否是无表单场景下后台提交文件至服务器的正确方案?- 如果是正确方案,该如何将文件正确传递给action函数?
代码片段
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) // 这里文件只剩下文件名 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); // 这里文件是完整的File对象 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} /> </> ); }
内容的提问来源于stack exchange,提问作者fabsie
相关产品推荐
相关产品推荐

