You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 11:30:00