【问题标题】:Passing file contents to outside variable将文件内容传递给外部变量
【发布时间】:2013-06-29 19:05:12
【问题描述】:

我正在使用 FileReader 和 HTML 文件对话框来读取脚本中的文件。如何将此文件的内容从 FileReader.onload 函数中传递出去?

function readFileData(evt) {
  var file = evt.target.files[0];
  var reader = new FileReader();

  reader.onload = function(e) {
    var contents = e.target.result;
  }
  reader.readAsText(file);
}
document.getElementById('file').addEventListener
    ('change', readFileData, false);

/* I want to access the contents here */

我尝试在 readFileData 和 onload 函数中添加返回,但我不确定它们返回到什么。

【问题讨论】:

  • 你想访问评论中的内容???
  • @Musa:你是真的这样解释这个问题,还是你只是个混蛋?

标签: javascript filereader


【解决方案1】:

我假设你知道,它的 async 等等。

所以,简短的回答是:不,你不能那样做。

但是,如果您希望将来的任何调用都可以全局访问内容,则可以这样:-

var contents;// declared `contents` outside
function readFileData(evt) {
  var file = evt.target.files[0];
  var reader = new FileReader();

  reader.onload = function(e) {
    contents = e.target.result; //<-- I removed the `var` keyword
  }
  reader.readAsText(file);
}

document.getElementById('file').addEventListener('change', readFileData, false);

var reasonableTimeToWaitForFileToLoad = 100000;

console.log(contents); //`contents` access first attempt: prints undefined



setTimeout(function() {
  console.log(contents);//`contents` access second attempt: prints the contents 'may be if the time allows.'
}, reasonableTimeToWaitForFileToLoad);

【讨论】:

  • 有没有办法确定文件何时加载?用户将上传可能需要一段时间才能加载的不同大小的大文件。我应该等到内容没有被循环定义吗?
  • 不,不要那样做。 Javascript是单线程的。因此,该循环将永远运行,直到浏览器崩溃。现在,知道文件已加载的唯一方法是reader.onload = function(e) {/**here**/}。您可以递归地使用setTimeout 来检查文件是否已加载。
  • 但是,IMO,setTimeout 是老式的。设计对事件做出反应的代码。你会很好的。
【解决方案2】:
var contents;
function readFileData(evt) {
  var file = evt.target.files[0];
  var reader = new FileReader();

  reader.onload = function(e) {
   contents = e.target.result;
  }

 reader.readAsText(file);

 reader.onloadend=function(e) {
   console.log(contents)
 }
}  

document.getElementById('file').addEventListener('change', readFileData, false);    

【讨论】:

  • 你必须解释你的答案
【解决方案3】:

这是一个范围界定问题。当您在 onload 中声明内容时,在该函数运行后它不再可用。您需要先声明该范围之外的内容。

var contents;
function readFileData(evt) {
  var file = evt.target.files[0];
  var reader = new FileReader();

  reader.onload = function(e) {
   contents = e.target.result;
  }
  reader.readAsText(file);
}
document.getElementById('file').addEventListener
    ('change', readFileData, false);

//make changes here
//contents should have the correct value

【讨论】:

  • 这绝对行不通,因为 FileReader 是异步的。
【解决方案4】:

首先,你必须意识到读取带有FileReader的文件是一个异步任务,你不能以同步的方式使用它。

有很多方法可以处理这个问题,但其中许多不适合推荐;)

我会选择以下两种方式之一:

1:您可以从 onload 事件处理程序中调用函数并将文件内容作为参数传递

2:您可以从 onload 事件处理程序中触发事件并将文件内容作为事件数据传递

【讨论】:

    【解决方案5】:

    只需在两个函数外部声明contents 并在内部函数内部分配给它:

    var contents;
    var outer_fn = function() {
      var inner_fn = function() {
        contents = '42';
      }
      inner_fn();
    }
    outer_fn();
    // here, `contents' is '42'
    

    【讨论】:

      【解决方案6】:

      我遇到了类似的挑战,这就是我用来解决问题的方法。

      var contents;
      function readFileData(evt) {
        var file = evt.target.files[0];
        var reader = new FileReader();
      
        reader.onload = function(e) {
         contents = e.target.result;
        }
      
       reader.readAsText(file);
      
       //calling to access the 'contents' variable
       accessFileContents();
      }  
      
      document.getElementById('file').addEventListener('change', readFileData, false);
      var wait4file2load = 1000;
      
      /* To access 'contents' here */
      function accessFileContents(){
        setTimeout(function(){
          console.log(contents);
        }, wait4file2load);
      }
      

      它不会给出undefined 值,因为我们在文件完全上传后调用它。

      【讨论】:

        【解决方案7】:

        我在 Angular 7(打字稿)中遇到了类似的问题,这就是我解决问题的方法。

        我想做的是访问在 fileReader -> reader.onload 中发生的 base64 转换

        然后将该参数传递给另一个方法,在该方法中我可以将其转换为 JSON 对象,然后将其发布到 API,因为我也想在帖子中发布另一个参数。 (本代码中没有添加)

        我首先要做的是声明我可能需要在方法之外访问的内容。

        base: any = null;
        base64File: any = null;
        fileToTest: any = null;
        

        然后我在上传事件触发时将 pdf 转换为 base64

        
        convertToBase64 (e){
        
          this.fileToTest = e.target.files[0];
          var reader = new FileReader();
              reader.onload = () => { 
                this.base64File = reader.result.slice(28); 
        };
        
        reader.onerror = function (error) {
          console.log('Error: ', error);
        
        }.bind(this.base64File);
        
        reader.readAsDataURL(this.fileToTest);
        
        return this.base64File;
        }
        
        

        最后用其他方法访问base64文件

        
         onSubmit() {
        
          console.log("base 64 file is visible", this.base64File);
        
            var base = 
              {
                "FileBase64": this.base64File,
                "Path": "document",
                "FileType": ".pdf"
              };
        
          console.log("JSON object visible", base);
          this.uploadService.base64Post(base);
        }   
        

        现在一切正常,希望这可以帮助其他人发现自己遇到同样的问题。

        使用 Angular 7,代码在组件文件中,而 post 函数在服务文件中。如果没有我的 cmets,组件文件中的代码完全一样。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2019-07-09
          • 1970-01-01
          • 2018-04-13
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2023-04-08
          • 1970-01-01
          相关资源
          最近更新 更多