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

React中URL.createObjectURL二次上传文件时无法生成对象URL问题

根因分析
  1. HTML规范中<source>标签的src属性变更不会触发父级<video>元素的资源重载行为,浏览器会沿用首次加载的视频资源,导致预览不刷新。
  2. 直接在JSX中调用URL.createObjectURL会在每次组件重渲染时重复生成对象URL,且未释放旧的URL会造成内存泄漏,也可能引发资源标识冲突。
修复方案
import { useState, useEffect } from 'react'

const VideoUpload = () => {
  const [videoFile, setVideoFile] = useState<File>()
  const [videoPreviewUrl, setVideoPreviewUrl] = useState<string>('')

  useEffect(() => {
    // 销毁上一个旧的对象URL,释放内存
    if (videoPreviewUrl) {
      URL.revokeObjectURL(videoPreviewUrl)
    }
    // 新文件存在时生成新的预览URL
    if (videoFile) {
      setVideoPreviewUrl(URL.createObjectURL(videoFile))
    }
    // 组件卸载时销毁最后生成的对象URL
    return () => {
      if (videoPreviewUrl) {
        URL.revokeObjectURL(videoPreviewUrl)
      }
    }
  }, [videoFile])

  const uploadVideo = (selectorFiles: FileList | null) => {
    if(selectorFiles?.length) {
      setVideoFile(selectorFiles[0])
    }
  }

  return (
    <>
      {/* 直接将预览地址绑定到video的src属性,变更时会自动触发资源重载 */}
      <video controls src={videoPreviewUrl} style={{maxWidth: '600px'}} />
      <br />
      <input type="file" accept="video/*" onChange={(e) => uploadVideo(e.target.files)} />
    </>
  )
}
可选兼容方案

如果必须保留<source>标签写法,给<video>标签绑定与当前文件关联的唯一key值即可,文件更新时key变化会触发整个video组件重新渲染,自动加载新资源:

<video controls key={videoFile ? `${videoFile.name}-${videoFile.lastModified}` : 'empty'}>
  <source src={videoPreviewUrl} />
</video>

内容的提问来源于stack exchange,提问作者k10a

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 01:36:01