React中使用draft-js实现文本编辑器图片上传预览 推迟上传至帖子提交时
解决方案:延迟上传draft-js编辑器内图片到提交阶段
核心逻辑:用户上传图片时不发起真实请求,仅生成临时预览地址插入编辑器,同时把图片文件暂存在本地,等用户提交帖子时再统一上传所有用到的图片,替换正文地址后提交到服务端。
改造步骤
1. 新增暂存待上传图片的状态
在EditorPost组件内新增状态存储待上传的图片映射:
const [pendingImages, setPendingImages] = useState<Record<string, File>>({})
2. 修改图片上传回调,取消实时上传
把原来的uploadImageCallBack改为仅生成临时地址,不发起接口请求:
function uploadImageCallBack(file: File): Promise<any> { return new Promise((resolve) => { // 生成唯一临时ID标识图片 const tempId = `temp_img_${Date.now()}_${Math.random().toString(36).slice(2)}` // 存入待上传列表 setPendingImages(prev => ({...prev, [tempId]: file})) // 生成临时预览地址供编辑器显示 const tempPreviewUrl = URL.createObjectURL(file) // 返回给编辑器,插入的图片先用临时地址 resolve({ data: { link: tempPreviewUrl, tempId: tempId } }) }) }
3. 提交帖子时统一处理图片
在提交帖子的逻辑中,先批量上传所有暂存的图片,替换正文临时地址,再提取封面:
const handleSubmitPost = async (postTitle: string) => { // 批量上传所有待上传的图片 const uploadTasks = Object.entries(pendingImages).map(async ([tempId, file]) => { const formData = new FormData() formData.append('image', file) const res = await axiosIntance.post('/upload', formData) return { tempId, realUrl: res.data.url } }) const uploadResults = await Promise.all(uploadTasks) // 替换正文中的临时图片地址为真实地址 let contentState = content.getCurrentContent() uploadResults.forEach(({tempId, realUrl}) => { // 遍历所有图片实体,匹配临时ID后替换为真实地址 contentState.getBlockMap().forEach(block => { block.findEntityRanges( character => character.getEntity() !== null, (start, end) => { const entityKey = block.getEntityAt(start) const entity = contentState.getEntity(entityKey) if (entity.getType() === 'IMAGE' && entity.getData().tempId === tempId) { contentState = contentState.mergeEntityData(entityKey, { src: realUrl }) } } ) }) }) const finalBody = draftToHtml(convertToRaw(contentState)) // 提取第一张图片作为帖子封面 const coverImg = uploadResults.length > 0 ? uploadResults[0].realUrl : '' // 提交到服务端存帖接口 await axiosIntance.post('/post/create', { title: postTitle, cover: coverImg, body: finalBody }) // 提交成功后清空暂存的图片 setPendingImages({}) }
优化建议
- 可以在编辑器状态变更时,检查被用户删除的图片,同步从pendingImages中移除,避免上传无效图片
- 组件卸载时调用
URL.revokeObjectURL释放临时预览地址的内存,避免泄漏 - 如果用户取消编辑,直接清空pendingImages即可,不会产生无效的服务端存储
内容的提问来源于stack exchange,提问作者Rainbow 77
相关产品推荐
相关产品推荐

