【问题标题】:Simplest, leanest implementation of FileReader API to grab a local image and display it?FileReader API 的最简单、最精简的实现来获取本地图像并显示它?
【发布时间】:2017-05-02 04:57:44
【问题描述】:

我正在尝试了解 FileReader API,以获取本地图像,然后将其显示在网页上。

我参考了 MDN 的页面集合(从这里开始:https://developer.mozilla.org/en-US/docs/Web/API/FileReader)以及 Treehouse,但最初似乎有很多复杂性需要克服,我热衷于让我的功能保持轻便、备用和尽量避免多余的杂物。

基本上我想部署最简单的脚本,而不让它过于简单。

这是我整理的getLocalImage() 函数:

var body = document.getElementsByTagName('body')[0];
var fileInput = document.querySelector('input[type=file]');

function getLocalImage() {
    var image = document.createElement('img');

    var reader = new FileReader();

    var imageFile = fileInput.files[0];
    reader.readAsDataURL(imageFile);

    reader.onload = function(e) {
        image.src = reader.result;
    }

    body.appendChild(image);
}

fileInput.addEventListener('change',getLocalImage,false);
<input type="file" />

我的问题很简单:

  1. 这个脚本能比它更简单吗? (我很怀疑,但我很想知道)。
  2. 更贴切的是,这个脚本是不是简单了?我是否遗漏了任何最佳实践? (例如,我是否也应该获取本地图像的尺寸,然后在网页上设置它们?)

【问题讨论】:

    标签: javascript refactoring filereader


    【解决方案1】:
    • 你可以为文件选择器定义accept属性,这样就只能选择图片:

      <input type="file" accept="image/*" />

    • change 回调中,您应该检查用户是否选择了文件,或者使用取消按钮清除了选择。

    • 您可以使用URL.createObjectURL 从选定的文件中创建图片网址。

    所以这里有两个选项,一旦您的示例重构,通过一些性能测量来查看 FileReader 和 ObjectUrl 的比较。

    function localImageSelected(event) {
        var files = event.target.files;
        if (files.length === 0) {
            return;
        } 
        var file = files[0];
    
        getImageSrcFromFile(file, function(src){
            var image = document.createElement('img');
            var now = performance.now();
            image.src = src;
            image.onload = function(){
                console.log('Image loaded in:', performance.now() - now);
            };
            document.body.appendChild(image);
        });     
    }
    
    function getImageSrcFromFile (file, cb) {
        var now = performance.now();
        var reader = new FileReader();
        reader.onload = function(e) {
            console.log('The url created in:', performance.now() - now);
            cb(reader.result);
        };
        reader.readAsDataURL(file);
    }
    
    document
        .querySelector('input[type=file]')
        .addEventListener('change', localImageSelected, false);
    

    并且使用 ObjectURL:

    function localImageSelected(event) {
        var files = event.target.files;
        if (files.length === 0) {
            return;
        } 
        var file = files[0];
    
        var image = document.createElement('img');
        var url = getImageSrcFromFile(file);
        var now = performance.now();
        image.src = url;
        image.onload = function(){
            console.log('Image loaded in:', performance.now() - now);
    
            //I do it here, but note that the url is not more usable. 
            // Or you can remove this line, then extra KBs are in memory until the page reload, 
            // usually it is not critical
            URL.revokeObjectURL(url);
        };
        document.body.appendChild(image);
    }
    
    function getImageSrcFromFile (file) {
        var now = performance.now();
        var url = URL.createObjectURL(file);
        console.log('The url created in:', performance.now() - now);
        return url;
    }
    
    document
        .querySelector('input[type=file]')
        .addEventListener('change', localImageSelected, false);
    

    我更喜欢 ObjectURL,因为它快 2 倍并且消耗更少的内存,但是您必须注意手动撤销 url,因为加载的图像会保留在内存中直到页面重新加载。当不再需要数据读取器的 base64 字符串时,垃圾收集器会对其进行清理。

    你可以在这里找到更好的比较FileReader vs. window.URL.createObjectURL

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-06-05
      • 2014-10-16
      • 1970-01-01
      • 2010-11-09
      • 2012-09-26
      • 2021-08-13
      • 1970-01-01
      • 2015-11-07
      相关资源
      最近更新 更多