原生js多文件本地上传预览

23 篇文章 1 订阅
12 篇文章 0 订阅

引子

<input> type 类型为 file 的 input 元素使得用户可以选择一个或多个元素以提交表单的方式上传到服务器上,或者通过 Javascript 的 File API 对文件进行操作 。

语法

属性说明
ValueDOMString 选择文件的路径
事件change 事件 input
支持的常用属性accept, multiple, required
IDL 属性文件 和 值
方法select()
  • 解释
    文件输入的 value 属性包括了一个 value 表示选择文件的路径DOMString。如果用户选择了多个文件,则该值表示他们选择的文件列表中的第一个文件。 可以使用输入的HTMLInputElement.files属性标识其他文件

  • 提示

  1. 如果选择了多个文件, 这个值表示第一个被选择的文件路径。JavaScript 可以通过 Input 的 FileList属性获取到其他的文件路径。
  2. 没有选择文件该值为空字符串。
  3. 为了阻止恶意软件猜测文件路径, 该值 以 C:\fakepath\为前缀。

使用

包括上面所说的 multiple 属性, 多个文件可以被同时选中. 只要用户所在的平台允许 (e.g. 摁住 Shift 或者 Control), 用户可以选择多个文件. 如果不希望多选, 忽略 multiple 属性.

在上面的例子中, 当表单被提交, 每个选中的文件名将被添加到 URL 参数中?file=file1.txt&file=file2.txt

获取选中文件信息
  • 选中文件通过 HTMLInputElement.files 属性返回 — 返回值是一个 FileList 对象,这个对象是一个包含了许多 File 文件的列表(你也可以想列表一样操作它).

  • 每个 File 对象包含了下列信息:

name: 文件名.
lastModified: UNIX timestamp 形式的最后修改时间.
lastModifiedDate: Date 形式的最后修改时间.
size: 文件的字节大小.
type: DOMString 文件的 MIME 类型.

限制允许的文件类型

accept 属性接受一个逗号分隔的 MIME 类型字符串, 如:

accept="image/png" or accept=".png" — 只接受 png 图片.
accept="image/png, image/jpeg" or accept=".png, .jpg, .jpeg" — PNG/JPEG 文件.
accept="image/*" — 接受任何图片文件类型.
accept=".doc,.docx,.xml,application/msword,application/vnd.openxmlformats-officedocument.wordprocessingml.document" — 接受任何 MS Doc 文件类型.
下面是一个更完整的例子:

示例代码

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>multiple file uploade</title>
</head>

<body>
    <h4>多文件上传</h4>
    <p>
        使用 opacity 而不是 visibility: hidden / display: none的原因是因为visibility和display会让input不可选择
    </p>
    <form>
        <div>
            <label for="image_uploads">点击选择多图片上传 (PNG, JPG)</label>
            <input type="file" id="image_uploads" name="image_uploads" accept=".jpg, .jpeg, .png" multiple>
        </div>
        <div class="preview">
            <p>No files currently selected for upload</p>
        </div>
        <div>
            <button>Submit</button>
        </div>
    </form>

    <script>
        // 获取 input 元素
        var input = document.querySelector('input');
        // 获取 preview 元素
        var preview = document.querySelector('.preview');
        // 将 input 变成透明的
        input.style.opacity = 0;
        // 监听 input 的 change 事件
        input.addEventListener('change', updateImageDisplay);

        // 监听函数
        function updateImageDisplay() {
            // while 循环清空 preview 中的内容. 
            while (preview.firstChild) {
                preview.removeChild(preview.firstChild);
            }

            // 获取 FileList 对象并且将选中文件保存到 curFiles 变量中
            var curFiles = input.files;
            // 检查是否没有选中文件
            if (curFiles.length === 0) {
                var para = document.createElement('p');
                para.textContent = 'No files currently selected for upload';
                preview.appendChild(para);
            } else {
                // 创建有序列表
                var list = document.createElement('ol');
                preview.appendChild(list);
                for (var i = 0; i < curFiles.length; i++) {
                    var listItem = document.createElement('li');
                    var para = document.createElement('p');

                    //检查文件类型是否正确
                    if (validFileType(curFiles[i])) {
                        // 在 div 中打印文件名称和 size
                        para.textContent = 'File name ' + curFiles[i].name + ', file size ' + returnFileSize(curFiles[i]
                            .size) + '.';
                        // 通过 window.URL.createObjectURL(curFiles[i]) 以及 css 产生预览图.
                        var image = document.createElement('img');
                        // 生成blob对象
                        image.src = window.URL.createObjectURL(curFiles[i]);

                        listItem.appendChild(image);
                        listItem.appendChild(para);

                    } else {
                        // 不正确则将结果告知用户
                        para.textContent = 'File name ' + curFiles[i].name +
                            ': Not a valid file type. Update your selection.';
                        listItem.appendChild(para);
                    }

                    list.appendChild(listItem);
                }
            }
        }

        // 自定义的 validFileType() 接受一个 File 对象作为参数, 然后检查文件类型是否在 accept 列表中.
        var fileTypes = [
            'image/jpeg',
            'image/pjpeg',
            'image/png'
        ]

        // 验证文件类型
        function validFileType(file) {
            for (var i = 0; i < fileTypes.length; i++) {
                if (file.type === fileTypes[i]) {
                    return true;
                }
            }

            return false;
        }

        // returnFileSize()方法接受一个数字作为参数以 KB/MB 的形式返回结果.
        function returnFileSize(number) {
            if (number < 1024) {
                return number + 'bytes';
            } else if (number > 1024 && number < 1048576) {
                return (number / 1024).toFixed(1) + 'KB';
            } else if (number > 1048576) {
                return (number / 1048576).toFixed(1) + 'MB';
            }
        }
    </script>
</body>

</html>
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值