前端图片预览功能实现

不少时候咱们都会有图片上传的功能需求,若是咱们先将图片上传到服务器,而后在将返回结果显示在前端,这样的操做性能开销太大,若是图片一多,简直要哭,并且万一还碰到了上传错误要删除的,那简直没法想象了。因此咱们须要先将图片在前端展现后,而后由用户确认没有问题了,再统一上传,这样才是比较理想的。css

input

type=file

相信你们都知道,要在前端实现图片的上传,咱们离不开的是一个 <input> type=file 的 input 元素,该元素能够容许用户选择一个或者多个文件。html

<input type="file">
复制代码

此时,咱们点击 input 元素,就能够浏览本地文件并选择上传。可是,此时咱们只能选择一个文件,而不能多个。这时就须要 <input> 标签的另外一个属性 multiple前端

multiple

multipla 属性容许用户选择多个文件,他是一个不须要值的属性,也就是说,只要你的 input 标签上出现了这个属性,那么不论其值是什么,他都会支持多文件选择。一般来讲咱们使用 multiple 只会使用其属性名,而不会给他加值web

<input type='file' multiple>
复制代码

accept

若是你尝试了以上标签及属性,你会发现你的不但能选择 image 文件,还能选择其余各类各样的文件。可是通常来讲对咱们有须要的只是 image 文件,至于其余什么的,爱咋咋地吧,只要不出来妨碍我就能够了。因此这时候咱们须要 accept 的属性来进行限制。accept 属性接受逗号分隔的 MIME 类型字符串:数组

1. accept='image/png' 或者 accept='.png' --只接受 .png 格式的图片
2. accept='iamge/png,image/jpeg' 或者 accept='.png, .jpg .jpeg' 接受 .png .jpeg .jpg 格式的图片
3. accept='image/*' 接受全部类型的 image 


    <input type='file' multiple accetp='image/*'>
复制代码

注: 'image/*' 在部分浏览器中(Chrome和Safari等Webkit浏览器)响应比较缓慢,能够用如下方法代替浏览器

<<input type="file" multiple accept='image/png, image/jpeg, image/jpg, image/svg, image/gif'> 
复制代码

样式

通常来讲咱们都会将 input 设置为 display:none, 而后经过 label 来设置其显示样式服务器

// css

    input{
        display:none;
    }
    label{
        // 关于label样式
    }

    // html

    <input type='file' multiple accept='image/png, image/jpeg, image/jpg, image/svg, image/gif' id='inputFile'>
    <label for="inputFile">上传图片</label>
复制代码

FileList 对象

选中文件经过 HTMLInputElement.files 属性返回了一个 FileList 对象,这个对象是一个包含了许多 file 文件的列表。每一个 file 对象包含了一下信息:app

1. name:文件名
2. lastModified:文件最后一次修改时间(时间戳形式)
3. lastModifiedDate:文件最后一次修改时间(UNIX timestamp形式)
4. size: 文件大小(byte 为单位)
5. type:文件 MIME 类型
复制代码

咱们能够经过对 input 标签监听 change 事件:异步

//  js

    document.getElementById('inputFile').addEventListener('change', changeHandler, false);

    function changeHandler(e) {
        var files = e.target.files;
        console.log(files) // 这里咱们能获取到所选择的文件信息,须要注意的一点是 files 是个类数组对象。
    } 
复制代码

FileReader or 对象 URL

当咱们获取到文件对象信息 files 了之后,咱们要如何将他在页面上预览出来,这里提供了两种方法:FileReader 或者 对象 URL。
这两种方法该如何使用,又有何区别呢?svg

1. FileReader

FileReader 实现了一种异步的读取机制。他必须先经过 FileReader() 构造函数建立出一个 fileReader 实例。该实例实现了一下几个方法和事件(部分):

  1. readerAsDataURL(file): 读取文件并以数据 URI 形式保存在 result 属性中

  2. load 事件:在文件加载成功后触发 load 事件

  3. error 事件:在文件加载失败后触发 error 事件

  4. progress 事件:在读取文件的过程当中触发 progress 事件,该事件能够近似(间隔性触发,不是实时响应)监听文件上传进度。该方法有三个属性:lengthComputable(进度信息是否可用), loaded(已经加载了多少), total总共有多少。

usage:

files.forEach(function(item) {
        var reader = new FileReader();
        reader.readAsDataURL(item);
        reader.onprogress = function(e) {
            if (e.lengthComputable) {
                // 简单把进度信息打印到控制台吧
                console.log(e.loaded / e.total + '%') 
            }
        }
        reader.onload = function(e) {
            var image = new Image()
            image.src = e.target.result
            body.appendChild(image)
        }
        reader.onerror = function(e) {
            console.log('there is an error!')
        }
    })
复制代码

2. 对象 URL

对象 URL 指的是引用保存在 File 或 Blob 中的数据 URL。使用对象 URL 的时候不用像 FIleReader 同样要先把数据读取到 JavaScript 中,他能够引用 内存中 URL 地址而使用。

建立对象 URL 方法: window.URL.createObjectURL()。兼容写法:

function creatObjectURL(file) {
        if (window.URL) {
            return window.URL.createObjectURL(file);
        } else if (window.webkitURL) {
            return window.webkitURL.createObjectURL(file);
        } else {
            return null
        }
    }
复制代码

usage:

files.forEach(function(item) {
        var url = createObjectURL(item)
        var image = new Image()
        image.src = url
        body.appendChild(image)
    })
复制代码

区别:

参(zhao)考(chao)

  1. FileReader 是异步操做,而对象 URL 是同步操做

  2. FileReader.readAsDataURL 返回的是一个包含更多字节的 base64 格式,createObejctURL 返回的是一个带 hash 的 URL。

  3. 因为二者返回形式不一样,FileReader.readerAsDataURL 会占用更多内存,可是当你再也不使用他的时候,他会自动释放内存,而 createObjectURL 则只有当你的页面关闭或者手动调用 revokeObejctURL 的时候才能释放内存。

  4. 从兼容性来讲: createObjectURL 和 FileReader.readerAsDataURL 都兼容 IE10+ 和现代全部主流浏览器

  5. createObjectURL 相对 FileReader.readerAsDataURL,效率较高。可是若是图片较多,则最好手动清除内存,能够把 URL 当作参数直接传给 window.URL.revokeObjectURL()。兼容写法:

    function revokeObjectURL(url) {
         if (widnow.URL) {
             return window.URL.revokeObjectURL(url)
         } else {
             return window.webkitURL.revokeObjectURL(url)
         }
     }
    复制代码

简单实现:

// css

    input{
        display:none;
    }
    label{
        // 关于label样式
    }

    // html

    <input type='file' multiple accept='image/png, image/jpeg, image/jpg, image/svg, image/gif' id='inputFile'>
    <label for="inputFile">上传图片</label>

    // js 

    var inputFile = document.getElementById('inputFile')
    var body = document.body || document.getElementsByTagName('body')[0]

    inputFile.addEventListener('change', changeHandler, false)

    function changeHandler(e) {
        var files = Array.from(e.target.files)
        files.forEach(function(item) {
            var image = new Image()
            image.src = createObjectURL(item)
            body.appendChild(image)
            image.onload = function() {
                revokeObjectURL(this.src)
            }
        })
    }

    function createObjectURL(file) {
        if (window.URL) {
            return window.URL.createObjectURL(file)
        } else {
            return window.webkitURL.createObjectURL(file)
        }
    }

    function revokeObjectURL(file) {
        if (window.URL) {
            return window.URL.revokeObjectURL(file)
        } else {
            return window.webkitURL.revokeObjectURL(file)
        }
    }

     

        } else {
            前端学习培训、视频教程、学习路线,添加威信  kaixin666haoyun  与我联系
        }
做者:爱创课堂前端技术分享 连接: 来源:掘金 著做权归做者全部。商业转载请联系做者得到受权,非商业转载请注明出处。
相关文章
相关标签/搜索