【问题标题】:Pass a parameter to FileReader onload event将参数传递给 FileReader onload 事件
【发布时间】:2013-05-31 23:50:45
【问题描述】:

我需要阅读用户提供的一些 csv 文件。使用拖放 div 将文件传递到页面/脚本,该 div 处理文件拖放如下:

function handleFileDrop(evt) {
    evt.stopPropagation();
    evt.preventDefault();
    var files = evt.dataTransfer.files; // FileList object.
    ...
}

我需要使用将其转换为数组的 csv 库来解析每个文件,但我还需要跟踪当前正在解析的文件名。这是我用来解析每个文件的代码:

for(var x = 0; x < files.length; x++){
    var currFile = files[x];
    var fileName = currFile.name;
    var reader = new FileReader();
    reader.onload = (function(theFile){
        return function(e){
            var csvArr = CSV.csvToArray( e.target.result, ";", true );
            console.log(csvArr); 
        };
    })(currFile);   
    reader.readAsText(currFile);
}

在此之前,一切正常。我还需要将文件名传递给reader.onload 事件,例如:

reader.onload = (function(theFile){
    return function(e){

       ***** I need to have fileName value HERE *****

    };
})(currFile); 

有可能吗?我怎样才能做到这一点?在此先感谢您的帮助,最好的问候

【问题讨论】:

    标签: javascript html filereader


    【解决方案1】:

    尝试以下方法:

    var reader = new FileReader();
    reader.onload = (function(theFile){
        var fileName = theFile.name;
        return function(e){
            console.log(fileName);
            console.log(e.target.result);
        };
    })(currFile);   
    reader.readAsText(currFile);
    

    在这里,每次将文件传递给外部方法时,您都会创建一个新的fileName 变量。然后,您将创建一个可以访问该变量的函数(由于闭包)并返回它。

    【讨论】:

    • 天才!非常感谢,我正在努力做到这一点。我想我现在开始理解闭包了!
    • 如何同时获取文件名和 reader.result 值?
    • @NiallJG 如果您查看分配给onload 属性的内容,我们实际上是在执行一个函数并传入currFile。在该函数中,theFile 只是我们传入的文件的不同名称。这允许我们存储对该文件名称的引用,一旦实际读取文件内容就可以访问该名称。
    • @John 内部函数是一个闭包,因为它在返回后保留了对fileName 变量的引用。您正在查看的语法通常称为 Immediately-invoked Function expression 或简称 IIFE。
    • @Antuan 如果您有一个文件数组,并且正在按顺序读取它们,那么最好采用不同的方法并创建一个引用当前数组索引的计数器变量。然后你就只有一个onload 可以访问原始文件数组和名称。请参阅codepen.io/anon/pen/jdXJRY?editors=1011 作为基本示例。如果文件很大,那么您可以考虑为每个文件插入一个 FileReader 并在 Workers 中读取它们以避免锁定浏览器。
    【解决方案2】:

    使用 Blob API

    使用new File / Blob API 可以更轻松地完成。

    您的第二个代码块 - 也解决了您的问题 - 可以重写为:

    for (let file of files){
     (new Blob([file])).text().then(x=>console.log(file.name,x));
    }
    

    Blob API 使用 Promises 而不是像 Filereader API 这样的事件,这样就减少了闭包的麻烦。 Arrow function(x=>)iteratorfor, 也让代码更加简洁。

    检查support

    使用 Fetch API

    也可以使用Fetch API Response Object 更容易完成。

    for (let file of files){
     (new Response(file)).text().then(x=>console.log(file.name,x));
    }
    

    注意构造函数中缺少Array []

    还有check support

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-01-05
      • 1970-01-01
      • 2016-10-09
      • 1970-01-01
      • 2011-07-10
      • 1970-01-01
      • 2010-10-24
      • 2013-06-29
      相关资源
      最近更新 更多