【问题标题】:Unable to read image with FileReader (see Update 2)无法使用 FileReader 读取图像(请参阅更新 2)
【发布时间】:2017-02-26 02:37:29
【问题描述】:

我正在尝试使用此 javascript 代码读取由 input[type=file] 字段选择的图像文件:

      var reader = new FileReader();
      var blob;
      reader.onloadend = function (e) {
        blob = e.target.result;
      }
      reader.readAsDataURL(this.files[0]);

但是当我在浏览器中运行代码时,我收到了这个错误:

TypeError: Argument 1 of FileReader.readAsDataURL is not an object.

任何人都可以看到这里出了什么问题?

更新

这是包含此 sn-p 的代码。应该提供有关导致错误的原因的更多上下文,我希望:

  $('#submit').on('click', function(){
    var $form = $( 'form.form' ), url = $form.attr( "action" ), str = $form.serialize();
    $('input[type=file]').each(function(){
      var reader = new FileReader();
      var blob;
      reader.onloadend = function (e) {
        blob = e.target.result;
      }
      reader.readAsDataURL(this.files[0]);
      str = str + "\u0026" + $(this).attr("name") + "=" + blob;
    });
    var posting = $.post( url, str );
    posting.done(function(data){
      if(data == "") {
        $("#alerta_sucesso").css("display", "block");
      } else {
        $("#alerta_erro").find("#texto").text(data);
        $("#alerta_erro").css("display", "block");
      }
    });
  });

更新 2

我设法更改代码并在没有错误的情况下执行它,但即便如此我也无法将图像存储在变量blob 中以将此数据发送到服务器。当前代码是这样的:

  $('#submit').on('click', function(){
    var $form = $( 'form.form' ), url = $form.attr( "action" ), str = $form.serialize();
    var input = $form.find('input[type=file]');
    $form.find('input[type=file]').each(function(){
      var id = $(this).attr("id");
      if(typeof id !== "undefined") {
        if(this.files.length > 0) {
          var reader = new FileReader();
          var blob;
          reader.onloadend = function (e) {
            blob = e.result;
          }
          reader.readAsDataURL(this.files[0]);
          str = str + "\u0026" + $(this).attr("name") + "=" + blob;
        }
      }
    });
    var posting = $.post( url, str );
    posting.done(function(data){
      if(data == "") {
        $("#alerta_sucesso").css("display", "block");
      } else {
        $("#alerta_erro").find("#texto").text(data);
        $("#alerta_erro").css("display", "block");
      }
    });
  });

我认为现在问题出在线路上:

blob = e.result;

有人知道这应该是什么值吗?

【问题讨论】:

  • 可以创建一个stacksn-ps来演示吗?
  • @guest271314 我用我之前发布的 sn-p 所在的完整代码更新了问题。我希望这可以为导致错误的原因提供更广泛的背景。
  • @guest271314 我想要完成的事情:提交input 字段选择的图像以及其余的文本字段(现在,这没有发生,因为函数 $.serialize 没有读取这个input[type=file] 归档)。
  • onloadend 提供 .resultFileReader.readAsDataURL() 异步调用。为什么发送查询字符串而不使用FormData()document 中是否有多个 <input type="file"> 元素?您可以在问题中包含html 吗?

标签: javascript jquery filereader


【解决方案1】:

FileReader 是异步的,执行发生在单个线程中。

这意味着当这行被调用时(我看不到str在任何地方被定义,如果没有,记得在附加它之前将其设置为初始字符串,即var str = "";):

str = str + "\u0026" + $(this).attr("name") + "=" + blob;

blob 还没有填充任何值,因为它需要等待整个功能块完成执行,这样才能执行处理程序中的代码。

您需要在回调中构建结果字符串:

var reader = new FileReader();
reader.onloadend = function() {
  str += "&" + $(this).attr("name") + "=" + this.result;
  // continue from here ...
};
reader.readAsDataURL(this.files[0]);

但是blob 在这段代码中不是一个blob(或者this.result 在我上面的更改之后),它是一个包含数据uri 的字符串。如果打算将其作为 URI 参数的一部分,则可能需要先对字符串进行编码(例如,请参见 encodeURIComponent - 使用图像作为数据 uri,您也可能会遇到长度限制,并且必须使用 POST)。

如果您需要一个实际的 blob,您甚至不需要使用 FileReader - 只需使用也是 blob 的文件对象(来自 this.files[n])。

【讨论】:

  • 几点: 1) str 定义在代码的开头——确切地说是第二行。 2)我按照建议在块内移动str += "&" + $(this).attr("name") + "=" + this.result;,但字符串仅出现在此块内。
  • 我只是在reader.onloadend = function() {...} 块内和var posting = $.post( url, str ); 之前可视化str。最后一个最先显示;之后的第一个。但是当我检查浏览器的开发工具时,这个参数不包括在其他参数中。
  • @KleberMota “但字符串仅出现在此块内”这是预期的并且应该是。这是一个异步操作,只有在整个加载完成后才能(安全地)附加结果。正如我所指出的,您需要从该处理程序块中继续(即发布结果等)。
【解决方案2】:

由于提供的信息有限,如果您尝试在 div 或 img 元素中显示图像,下面显示了两种方法。

解决方案 1

$('input').change(function() {

  var fr = new FileReader;

  fr.onloadend = function() {
    $("#target").attr('src', fr.result);
  };
  console.log(this.files[0]);
  //fr.readAsDataURL(this.files[0]);

});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<input type="file">
<img id="target">

解决方案 2

$('input').change(function() {

  var fr = new FileReader;

  fr.onload = function() {
    var img = new Image;
    img.onload = function() {
      var c = document.getElementById("cvs");
      var ctx = c.getContext("2d");
      ctx.drawImage(img, 0, 0, 200, 180);
    }
    img.src = fr.result;

  };
  console.log(this.files[0]);
  fr.readAsDataURL(this.files[0]);

});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<input type="file">
<canvas id="cvs"></canvas>

这些将读取您的文件,您可以动态获取文件名和其他属性。

【讨论】:

  • 答案未解释 OP 中描述的错误。 javascript 在 Question 应该返回预期的结果。
  • 看不出他的代码有什么问题。它工作正常,由于他提出了一个广泛的问题,我给出了两个解决方案。
  • 你能重现问题中描述的错误吗? OP 的javascript 有什么问题?
  • 试图重现它,但我离原来的错误还很远。我只得到TypeError: Failed to execute 'readAsDataURL' on 'FileReader': parameter 1 is not of type 'Blob'. 他的代码必须有一些额外的东西,否则他应该发布他的错误的堆栈跟踪。
  • @Inuka 我用我之前发布的 sn-p 所在的完整代码更新了问题。我希望这可以为导致错误的原因提供更广泛的背景。
【解决方案3】:

所以,我终于设法用这种方法解决了这个问题:

  var str = "";

  $('input[type=file]').on("change", function(){
    var id = $(this).attr("id");
    var name = $(this).attr("name");
    if(typeof id !== "undefined") {
      if(this.files.length > 0) {
        reader = new FileReader();
        reader.onloadend = function () {
          str += "&" + name + "=" + this.result;
        }
        reader.readAsDataURL(this.files[0]);
      }
    }
  });

  $('#submit').on('click', function(){
    var $form = $( 'form.form' );
    var url = $form.attr( "action" );
    str += $form.serialize();
    $.post(url, str, function(data){
      if(data == "") {
        $("#alerta_sucesso").css("display", "block");
      } else {
        $("#alerta_erro").find("#texto").text(data);
        $("#alerta_erro").css("display", "block");
      }
    });
  });

现在图像作为字符串发送到服务器,可以由 PropertyEditorSupport 类处理;这就是我现在正在尝试做的事情。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-01-12
    • 1970-01-01
    • 1970-01-01
    • 2020-09-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多