无法使用 FileReader 读取图像(请参阅更新 2)

Unable to read image with FileReader (see Update 2)

我正在尝试使用此 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.

有人能看出这里出了什么问题吗?

更新

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

  $('#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;

有人知道这个的正确值是多少吗?

鉴于所提供的信息有限,如果您尝试在 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>

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

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 - 将图像作为 data-uri 您也可能 运行 进入长度限制并且必须使用 POST).

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

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

  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 class 处理;这就是我现在正在尝试做的事情。