如何在Redux中存储图片和视频文件,解决非序列化报错问题
问题根因
Redux Toolkit默认开启了序列化值校验,File、ArrayBuffer这类浏览器原生对象不属于可序列化值,所以会抛出警告;同时JSON序列化不会处理这类复杂对象的内置属性,所以直接JSON.stringify()会得到空对象。
最优解决方案(适配多步骤表单不丢数据的需求)
优先选择调整Redux序列化规则+直接存储原生File对象的方案,无额外格式转换开销,适合照片、大体积视频等任意格式的上传文件:
- 修改Redux Store配置,忽略文件相关字段的序列化校验
如果你使用的是Redux Toolkit,按如下方式调整配置即可:
import { configureStore } from '@reduxjs/toolkit' import formSlice from './formSlice' export const store = configureStore({ reducer: { form: formSlice, }, middleware: (getDefaultMiddleware) => getDefaultMiddleware({ serializableCheck: { // 替换为你实际的文件存储action类型 ignoredActions: ['form/setUploadPhoto', 'form/setUploadVideo'], // 替换为你实际的表单文件存储路径 ignoredPaths: ['form.uploadedPhoto', 'form.uploadedVideo'], }, }), })
- 调整Dropzone组件逻辑,直接传递原File对象
你当前的代码读取文件为ArrayBuffer完全是冗余操作,直接把原生File对象传递给onResult存入Redux即可,如需保留原有加载进度展示,调整后的onDrop逻辑如下:
const onDrop = useCallback(acceptedFiles => { acceptedFiles.forEach(file => { const reader = new FileReader(); reader.onerror = () => setError(true); reader.onprogress = data => { if (data.lengthComputable) { const progress = parseInt( (data.loaded / data.total) * 100, 10 ); setProgress(progress); } }; // 读取完成后传递原File对象,不需要传reader.result reader.onloadend = () => onResult(file); reader.readAsArrayBuffer(file); }); // 记得把onResult加入依赖数组避免闭包问题 }, [onResult]);
后续提交表单时,直接从Redux中取出File对象组装FormData上传即可,不需要做任何格式转换。
兼容页面刷新保留文件的补充方案
如果需求要求用户刷新页面后上传的文件不丢失,可以将文件转为Base64字符串存储:
- 照片文件体积小,可直接转Base64存入Redux+LocalStorage
- 视频文件体积较大时,建议存入IndexedDB避免触发LocalStorage的5MB容量限制
转换时只需将reader.readAsArrayBuffer改为reader.readAsDataURL,拿到的结果就是可直接序列化的Base64字符串。
内容的提问来源于stack exchange,提问作者seven
相关产品推荐
相关产品推荐

