可以直接用 URL.createObjectURL(file) 实现本地图片预览,无需 fetch;若需服务端处理(如加水印),则用 fetch 上传后调用 response.blob() 再 createObjectURL,并及时 revoke 释放内存。

可以直接用 fetch 获取上传的图片文件(比如通过 <input type="file">),再用 URL.createObjectURL 生成临时 URL,赋值给 <img> 的 src 实现预览。关键在于:不是用 fetch 去请求远程地址,而是把本地 File 对象当作 fetch 的响应体来“模拟”一个可读流,从而兼容后续处理逻辑——但更简单直接的做法其实是跳过 fetch,直接用 createObjectURL。不过若你确实需要在预览前对图片做 fetch 风格的处理(例如加水印接口返回新图、或走代理服务),下面分两种常见场景说明:
场景一:纯前端本地预览(推荐,无需 fetch)
用户选中图片后,不发请求,直接生成预览 URL:
- 监听
input[type="file"]的change事件 - 取到
files[0](即File对象,它继承自Blob) - 调用
URL.createObjectURL(file)得到一个以blob:开头的临时地址 - 把这个地址赋给
<img src="...">即可立即显示
✅ 优点:零网络请求、秒出、无跨域问题、内存自动管理(记得用 URL.revokeObjectURL 清理)。
场景二:上传后服务端处理再预览(需 fetch)
比如用户上传图片 → 后端加水印/压缩 → 返回处理后的图片流 → 前端预览:
- 用
FormData包裹File,fetch('/upload', { method: 'POST', body: formData }) - 确保后端响应头包含
Content-Type: image/*(如image/png) - 用
response.blob()获取响应的 Blob 数据 - 再调用
URL.createObjectURL(blob)生成预览地址
⚠️ 注意:不能直接把 response.url 当预览地址(那是上传接口地址,不是图片地址);必须用 blob() 提取响应体内容。
清理临时 URL 防止内存泄漏
createObjectURL 创建的链接会持续占用内存,直到被显式释放或页面卸载:
- 每次生成新 URL 前,先用
URL.revokeObjectURL(oldUrl)清掉旧的 - 在组件卸载、图片替换、或用户取消预览时调用 revoke
- 例如:img.onload = () => URL.revokeObjectURL(img.src) 是常见误区——此时
img.src已是 blob URL,但 onload 后仍需手动 revoke,且应在不再需要时立刻做,而非等 onload
完整小例子(场景一)
HTML:
<input type="file" accept="image/*" id="uploader"><br> <img id="preview" width="200">
JS:
const input = document.getElementById('uploader');<br>
const img = document.getElementById('preview');<br>
input.addEventListener('change', async e => {<br>
if (img.src) URL.revokeObjectURL(img.src);<br>
const file = e.target.files[0];<br>
if (!file) return;<br>
img.src = URL.createObjectURL(file);<br>
});

















