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

转换文件为Base64格式时如何保留原文件名?React项目实现疑问

根因说明

readAsDataURL返回的Data URL仅包含媒体类型、编码规则和文件内容,本身不携带文件名信息,浏览器识别该类字符串为文件时默认命名为Data属于规范内的预期行为。
原有代码存在两点疏漏:

  • 直接将事件对象e传入readAsDataURL,未从e.target.files中读取原始File实例
  • 未手动存储File实例自带的name属性(即原始文件名)

异常效果如下图:
效果截图

修复实现

方案1:FileReader读取base64版本

适合需要直接传输base64内容给后端的场景:

const handleGetFiles = (e) => {
  // 读取选中的所有文件
  const selectedFiles = Array.from(e.target.files);
  selectedFiles.forEach((file, idx) => {
    const reader = new FileReader();
    reader.readAsDataURL(file);
    reader.onload = () => {
      fileCollection((prev) => [...prev, {
        id: Date.now() + idx, // 用时间戳加下标保证唯一ID
        data: reader.result,
        fileName: file.name, // 存储原始文件名
        fileType: file.type,
        size: file.size
      }]);
    }
  })
}

<Input 
  accept="image/*,video/*" 
  id="contained-button-file" 
  multiple 
  type="file" 
  onChange={handleGetFiles}
/>

后续使用时直接读取存储的fileName字段即可展示/使用原始文件名,示例渲染逻辑:

fileCollection.map(item => (
  <div key={item.id}>
    <p>{item.fileName}</p>
    {item.fileType.startsWith('image/') && <img src={item.data} alt={item.fileName} />}
  </div>
))

方案2:URL.createObjectURL版本

适合前端本地预览场景,性能远高于读取base64:

const handleGetFiles = (e) => {
  const selectedFiles = Array.from(e.target.files);
  const newFiles = selectedFiles.map((file, idx) => ({
    id: Date.now() + idx,
    previewUrl: URL.createObjectURL(file),
    fileName: file.name,
    rawFile: file // 后续上传可直接使用原始File对象
  }))
  fileCollection(prev => [...prev, ...newFiles])
}

// 组件卸载时释放objectURL占用的内存,避免内存泄漏
useEffect(() => {
  return () => {
    fileCollection.forEach(item => {
      if (item.previewUrl) URL.revokeObjectURL(item.previewUrl)
    })
  }
}, [])

补充工具方法:base64转标准File对象

如果需要把已存储的base64内容转为带正确文件名的标准File对象用于上传,可使用以下方法:

const dataURLtoFile = (dataUrl, fileName) => {
  const arr = dataUrl.split(',');
  const mime = arr[0].match(/:(.*?);/)[1];
  const bstr = atob(arr[1]);
  let n = bstr.length;
  const u8arr = new Uint8Array(n);
  while(n--){
    u8arr[n] = bstr.charCodeAt(n);
  }
  return new File([u8arr], fileName, {type: mime});
}

// 调用示例
const targetFile = dataURLtoFile(storedData, storedFileName)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 03:15:03