我悟了!原来本地图片预览还能这样搞

news/2025/2/21 9:09:17/文章来源:https://www.cnblogs.com/leadingcode/p/18724493
  • Hey, 我是 Immerse
  • 本文首发于 【沉浸式趣谈】,我的个人博客 https://yaolifeng.com 也同步更新。
  • 转载请在文章开头注明出处和版权信息。
  • 如果本文对您有所帮助,请点赞、评论、转发,支持一下,谢谢!

我悟了!原来本地图片预览还能这样搞

在网页开发中,经常会遇到需要让用户上传图片并在上传前进行预览的需求。这样做的好处显而易见:用户可以立即看到自己选择的图片是否正确,避免了不必要的上传和服务器资源浪费,提升了用户体验。

今天,我们就来一起学习如何使用原生 JavaScript 实现本地图片上传预览功能。我们将使用两种常用的 API:FileReadercreateObjectURL,并分别进行详细讲解和示例演示。

准备工作:HTML 结构

首先,我们需要在 HTML 中搭建一个简单的结构,用于文件上传和图片预览。主要包含两个元素:

  1. <input type="file">: 用于让用户选择本地文件。
  2. <img>: 用于展示预览图片。
<!DOCTYPE html>
<html><head><title>本地图片上传预览</title></head><body><h1>本地图片上传预览</h1><input type="file" id="imageUpload" accept="image/*" /> <br /><br /><imgid="imagePreview"src="#"alt="图片预览"style="max-width: 300px; max-height: 300px; border:1px solid #ccc;"/><script>// JavaScript 代码将在这里编写</script></body>
</html>

在上面的 HTML 代码中:

  • <input type="file" id="imageUpload" accept="image/*"> 创建了一个文件上传控件,id="imageUpload" 方便我们之后用 JavaScript 获取到它。accept="image/*" 限制了用户只能选择图片类型的文件,image/* 表示接受任何类型的图片文件。
  • <img id="imagePreview" src="#" alt="图片预览" ...> 创建了一个 <img> 标签,id="imagePreview" 同样是为了方便 JavaScript 操作。src="#" 先设置一个默认的无效图片地址,alt="图片预览" 是当图片无法显示时的替代文字。style="..." 设置了图片预览区域的最大宽高和边框样式,您可以根据实际需求调整。

方法一:使用 FileReader API

FileReader 是一个非常强大的 API,它可以异步读取用户本地文件内容。对于图片预览来说,我们可以使用 FileReader 将图片文件读取为 Data URL,然后将其设置为 <img> 标签的 src 属性,从而实现预览。

步骤 1:获取元素

首先,在 <script> 标签中,我们需要获取到 HTML 中的 input fileimg 元素:

const imageUpload = document.getElementById('imageUpload');
const imagePreview = document.getElementById('imagePreview');

步骤 2:监听 change 事件

我们需要监听 input filechange 事件。当用户选择了文件后,这个事件会被触发。

imageUpload.addEventListener('change', function () {const file = imageUpload.files[0]; // 获取用户选择的文件if (file) {// 确保用户选择了文件// ... (FileReader 的代码将在这里编写) ...} else {// 如果用户没有选择文件,可以重置预览图片imagePreview.src = '#'; // 恢复默认的无效图片地址imagePreview.alt = '图片预览';}
});

步骤 3:创建 FileReader 对象并读取文件

change 事件处理函数中,我们需要创建 FileReader 对象,并使用 readAsDataURL() 方法来读取文件内容。readAsDataURL() 方法会将文件读取为 Data URL 格式的字符串。

imageUpload.addEventListener('change', function () {const file = imageUpload.files[0];if (file) {const reader = new FileReader(); // 创建 FileReader 对象reader.onload = function (e) {// 当文件读取完成后,会触发 onload 事件imagePreview.src = e.target.result; // 将 Data URL 设置为 <img> 的 src 属性imagePreview.alt = file.name; // 可以将文件名设置为 alt 属性,增强可访问性};reader.readAsDataURL(file); // 开始读取文件,读取完成后会触发 onload 事件} else {imagePreview.src = '#';imagePreview.alt = '图片预览';}
});

代码解释:

  • const reader = new FileReader();: 创建一个新的 FileReader 对象。
  • reader.onload = function(e) { ... }: 设置 FileReaderonload 事件处理函数。当文件读取成功后,这个函数会被调用。
    • e.target.result: 在 onload 事件中,e.target.result 属性包含了读取到的文件内容,对于 readAsDataURL() 方法来说,这里就是 Data URL 字符串。
    • imagePreview.src = e.target.result;: 将 Data URL 字符串设置为 imagePreview (即 <img> 标签) 的 src 属性,浏览器会自动解析 Data URL 并显示图片。
    • imagePreview.alt = file.name;: 可选操作,将上传的文件名设置为 <img> 标签的 alt 属性,这有助于提高页面的可访问性。
  • reader.readAsDataURL(file);: 调用 readerreadAsDataURL() 方法开始异步读取文件。参数 file 就是用户选择的文件对象。

完整代码示例 (FileReader 方法):

<!DOCTYPE html>
<html><head><title>本地图片上传预览 (FileReader)</title></head><body><h1>本地图片上传预览 (FileReader)</h1><input type="file" id="imageUpload" accept="image/*" /> <br /><br /><imgid="imagePreview"src="#"alt="图片预览"style="max-width: 300px; max-height: 300px; border:1px solid #ccc;"/><script>const imageUpload = document.getElementById('imageUpload');const imagePreview = document.getElementById('imagePreview');imageUpload.addEventListener('change', function () {const file = imageUpload.files[0];if (file) {const reader = new FileReader();reader.onload = function (e) {imagePreview.src = e.target.result;imagePreview.alt = file.name;};reader.readAsDataURL(file);} else {imagePreview.src = '#';imagePreview.alt = '图片预览';}});</script></body>
</html>

方法二:使用 createObjectURL API

createObjectURL (或者更准确的说是 URL.createObjectURL()) 是另一个用于创建临时 URL 的 API。与 FileReader 不同,createObjectURL 直接为文件对象创建一个临时的 URL,这个 URL 可以直接设置为 <img>src 属性,而无需读取文件内容。

步骤 1 & 步骤 2: 获取元素和监听 change 事件 (与 FileReader 方法相同)

这部分代码和 FileReader 方法完全一样,您可以直接复制粘贴。

const imageUpload = document.getElementById('imageUpload');
const imagePreview = document.getElementById('imagePreview');imageUpload.addEventListener('change', function () {const file = imageUpload.files[0];if (file) {// ... (createObjectURL 的代码将在这里编写) ...} else {imagePreview.src = '#';imagePreview.alt = '图片预览';}
});

步骤 3:使用 createObjectURL 创建临时 URL

change 事件处理函数中,使用 URL.createObjectURL(file) 方法为选择的文件对象创建一个临时 URL,并将其设置为 <img>src 属性。

imageUpload.addEventListener('change', function () {const file = imageUpload.files[0];if (file) {const imageUrl = URL.createObjectURL(file); // 创建临时 URLimagePreview.src = imageUrl; // 将临时 URL 设置为 <img> 的 src 属性imagePreview.alt = file.name;} else {imagePreview.src = '#';imagePreview.alt = '图片预览';}
});

代码解释:

  • const imageUrl = URL.createObjectURL(file);: 调用 URL.createObjectURL(file) 方法,传入用户选择的文件对象 file,它会返回一个临时的 URL 字符串。这个 URL 代表了文件在内存中的位置。
  • imagePreview.src = imageUrl;: 将 imageUrl 设置为 imagePreviewsrc 属性,浏览器会根据这个临时 URL 加载并显示图片。

需要注意:

  • createObjectURL 创建的 URL 是临时的,它指向的是浏览器内存中的文件数据。当页面关闭或文档卸载时,这些临时 URL 会被释放。
  • 如果您需要手动释放通过 createObjectURL 创建的 URL,可以使用 URL.revokeObjectURL(imageUrl) 方法。虽然在简单的图片预览场景下,浏览器通常会自动管理这些临时 URL,但在更复杂的应用中,手动释放可能是一个好习惯,尤其是在处理大量文件或需要长时间保持页面活跃的情况下。

完整代码示例 (createObjectURL 方法):

<!DOCTYPE html>
<html><head><title>本地图片上传预览 (createObjectURL)</title></head><body><h1>本地图片上传预览 (createObjectURL)</h1><input type="file" id="imageUpload" accept="image/*" /> <br /><br /><imgid="imagePreview"src="#"alt="图片预览"style="max-width: 300px; max-height: 300px; border:1px solid #ccc;"/><script>const imageUpload = document.getElementById('imageUpload');const imagePreview = document.getElementById('imagePreview');imageUpload.addEventListener('change', function () {const file = imageUpload.files[0];if (file) {const imageUrl = URL.createObjectURL(file);imagePreview.src = imageUrl;imagePreview.alt = file.name;} else {imagePreview.src = '#';imagePreview.alt = '图片预览';}});</script></body>
</html>

两种方法的比较

特性 FileReader createObjectURL (URL.createObjectURL)
兼容性 较好,支持更老版本的浏览器 相对较好,现代浏览器均支持,但老版本浏览器可能不支持
性能 对于大文件,读取和编码为 Data URL 可能会较慢 对于大文件,创建临时 URL 速度快,性能更优
数据处理 将文件读取为 Data URL (Base64 编码字符串) 创建指向内存中文件数据的临时 URL
持久化 Data URL 可以被持久化保存 (例如,存储在数据库) 临时 URL 无法持久化保存,页面关闭或卸载后失效
代码复杂度 代码稍复杂,需要处理 onload 事件等 代码更简洁,直接创建 URL 即可
资源释放 不需要显式释放资源 建议在复杂场景中手动释放 URL (URL.revokeObjectURL),简单场景浏览器会自动管理
优点 兼容性好,Data URL 可持久化保存 性能好,代码简洁,尤其处理大文件更高效
缺点 大文件处理性能相对较差,Data URL 字符串较长 兼容性稍逊,临时 URL 不可持久化,需注意 URL 生命周期
适用场景 - 需要兼容老版本浏览器时
- 需要持久化保存图片数据时
- 追求性能,尤其处理大文件时
- 不需要持久化保存图片数据时

如何选择?

  • 如果注重兼容性,或者需要将图片数据持久化保存,可以选择 FileReader。
  • 如果更注重性能,尤其是处理大文件,并且不需要持久化保存图片数据,可以选择 createObjectURL。 对于大多数现代网页应用来说,createObjectURL 通常是一个更优的选择,因为它更简洁高效。

总结

好啦,简单总结一下 FileReadercreateObjectURL 这俩兄弟。

FileReader 就像个老实人:

  • 优点: 兼容性好,数据格式(Data URL)能存起来以后用。
  • 缺点: 大文件处理慢一点点。
  • 适合: 要兼容老浏览器,或者需要保存图片数据。

createObjectURL 像个急性子:

  • 优点: 速度快,尤其大文件预览嗖嗖的。 代码简单。
  • 缺点: 临时链接用完就没了,不方便存,兼容性稍逊一点点(但也够用啦)。
  • 适合: 追求速度,预览完就完事儿,不用保存图片。

怎么选?

  • 要稳妥、要存图 -> FileReader
  • 要速度、图不存 -> createObjectURL

总之,根据你的实际情况选就行!

希望这个简短总结能帮到你快速做决定。

动手试试才是王道! 加油!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/886746.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

octave画高通滤波、超前,滞后补偿器的幅频响应图

octave代码非常简单:pkg load control s=tf(s); k=0.5; sysG1=k*(0.005*s)/(0.005*s+1); sysG2=k*(0.8*s+1)/(0.1*s+1); sysG3=k*(s+1)/(5*s+1); figure bode(sysG1) figure bode(sysG2) figure bode(sysG3)也可以借助循环,看如下代码:1 pkg load control2 s=tf(s);3 k=0.5;…

frame切换/窗口切换

frame切换/窗口切换 切换到frame点击这里,边看视频讲解,边学习以下内容 请大家点击这里,打开这个链接 如果我们要 选择 下图方框中 所有的 蔬菜,使用css选择,怎么写表达式? 当然,要先查看到它们的html元素特征大家可能会照旧写出如下代码:from selenium import webdriv…

选择元素的基本方法

选择元素的基本方法点击这里,边看视频讲解,边学习以下内容对于百度搜索页面,如果我们想自动化输入 白月黑羽 ,怎么做呢? 这就是在网页中,操控界面元素。 web界面自动化,要操控元素,首先需要 选择 界面元素 ,或者说 定位 界面元素 就是 先告诉浏览器,你要操作 哪个 …

操控元素的基本方法

操控元素的基本方法 点击这里,边看视频讲解,边学习以下内容选择到元素之后,我们的代码会返回元素对应的 WebElement对象,通过这个对象,我们就可以 操控 元素了。 操控元素通常包括 点击元素在元素中输入字符串,通常是对输入框这样的元素获取元素包含的信息,比如文本内容…

CClink IEF Basic设备数据 转EthernetIP项目案例

VFBOX协议转换网关支持PLC,modbus,EthernetIP,Profinet,CCLink,EtherCAT,IEC61850,IEC104,bacnet,DLT645,HJ212,opc ua,opc da,DNP3。目录 1 案例说明 1 2 VFBOX网关工作原理 1 3 准备工作 2 4 网关采集CCLINK IEF BASIC数据 2 5 使用ETHERNETIP转发数据 5 6 案例…

SciTech-EECS-BigDataAIML-NN(神经网络): Forward NN(前向传播算法)

SciTech-EECS-BigDataAIML-NN(神经网络): Forward NN(前向传播算法)

微信小程序-实现微信授权自动登录功能

显示效果 授权前界面授权弹框界面 采用了wx.getUserProfile API申请用户信息,若基础库版本过高,例如3.7.7,则不会显示弹窗,默认为允许状态。若基础库版本降低,例如2.25.4,则会显示弹窗,如下图所示授权后界面前端部分 基础封装 新建utils文件夹,在该文件夹下新建login.j…

为DeepSeek添加本地知识库

为什么要尝试给DeepSeek添加本地知识库呢?作为一个程序员,以前也用过很多AI产品,直到春节DeepSeek爆火,成功在自己的电脑上把AI模型跑起来的时候才真正感受到AI已近在咫尺。未来很多应用和项目都离不开这个工具。或许在我们OA系统中会出现一个AI小助手,我们会问它差旅费报…

SciTech-EECS-Circuits-Digital(数字电路): Latch(锁存器) + Flip/Flop(触发器) + 记忆存储电路

SciTech-EECS-Circuits-Digital(数字电路) Latch(锁存器)Flip/Flop(触发器)记忆存储电路

山石网科阿里云通义灵码,开启研发“AI智造”新时代

近日,山石网科正式宣布全面接入阿里云通义灵码企业专属版,这标志着山石网科在研发智能化、自动化领域迈出重要一步,为研发工作注入强大的AI动力,实现多维度的效率飞跃。近日,山石网科正式宣布全面接入阿里云通义灵码企业专属版,这标志着山石网科在研发智能化、自动化领域…

frame/tab 切换,一些技巧

点击这里,边看视频讲解,边学习以下内容 frame切换 请大家点击这里,打开这个链接 如果我们要 选择 下图方框中 所有的 蔬菜,使用css选择,怎么写表达式? 当然,要先查看到它们的html元素特征大家可能会照旧写出如下代码:from playwright.sync_api import sync_playwrightp…

CSS选择器 定位方法

定位元素的重要性 前面这段代码from playwright.sync_api import sync_playwrightp = sync_playwright().start() browser = p.chromium.launch(headless=False) page = browser.new_page() page.goto("https://www.byhy.net/cdn2/files/selenium/stock1.html")# 输入…