为了账号安全,请及时绑定邮箱和手机立即绑定

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

标签:
JavaScript
  • 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 />
        <img
            id="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" class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="#" alt="图片预览" ...> 创建了一个 <img> 标签,id="imagePreview" 同样是为了方便 JavaScript 操作。class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="#" 先设置一个默认的无效图片地址,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 />
        <img
            id="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); // 创建临时 URL
        imagePreview.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 />
        <img
            id="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

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

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

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

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 2
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消