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

199 天前
 Lcode01

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

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

今天,我们就来一起学习如何使用原生 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 代码中:

方法一:使用 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 = '图片预览';
    }
});

代码解释:

完整代码示例 (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 = '图片预览';
    }
});

代码解释:

需要注意:

完整代码示例 (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 生命周期
适用场景 - 需要兼容老版本浏览器时
- 需要持久化保存图片数据时
- 追求性能,尤其处理大文件时
- 不需要持久化保存图片数据时

如何选择?

总结

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

FileReader 就像个老实人:

createObjectURL 像个急性子:

怎么选?

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

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

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

1275 次点击
所在节点    分享发现
1 条回复
Lcode01
199 天前
欢迎关注公众号: [沉浸式趣谈] 查看更多内容 ~

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/1112687

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX