【问题标题】:Why some browsers make Blob object empty? How to prevent it? [duplicate]为什么有些浏览器将 Blob 对象设为空?如何预防? [复制]
【发布时间】:2018-09-14 16:32:55
【问题描述】:

我正在使用 Ruby on Rails5,并使用 heroku 爱好。然后我想让用户从 Javascript 中选择、裁剪并直接将图像上传到 Amazon s3 like this article

我正在使用 jQuery-file-upload 和cropper.js。

下面的代码在我的 MacBook Pro 上的 chrome 中正常工作,但是,当涉及到 iOS 上的 safari 或 safari 时,iOS 上的 chrome 会在 s3 上生成空文件(但具有正确的名称)。

$(function() {
  $('.directUpload').find("input:file").each(function(i, elem) {
    var fileInput    = $(elem);
    var form         = $(fileInput.parents('form:first'));
    var submitButton = form.find('input[type="submit"]');
    var progressBar  = $("<div class='bar'></div>");
    var barContainer = $("<div class='progress'></div>").append(progressBar);
    fileInput.after(barContainer);

    var lastData = null;
    submitButton.on('click', function(){
    $('form').submit(function(){
      return false;
      });
     // get cropped data
     $('#crop_img').cropper('getCroppedCanvas').toBlob(function (blob){
        lastData.files[0] = new File([blob], lastData.files[0].name);
        lastData.originalFiles[0] = lastData.files[0];
        lastData.submit();
      })
   });

    fileInput.fileupload({
    fileInput:       fileInput,
    url:             form.data('url'),
    type:            'POST',
    autoUpload:       false,
    formData:         form.data('form-data'),
    paramName:        'file', // S3 does not like nested name fields i.e. name="user[avatar_url]"
    dataType:         'XML',  // S3 returns XML if success_action_status is set to 201
    replaceFileInput: false,
    acceptFileTypes: /(\.|\/)(gif|jpe?g|png)$/i,
    // singleFileUploads: false,
    maxNumberOfFiles: 1,
    sequentialUploads: true,
    limitMultiFileUploads:1,
    limitConcurrentUploads: 1,

    add: function(e, data){
      if (data.files && data.files[0]) {
        var reader = new FileReader();
        reader.onload = function(e) {
          $('.preview').empty();
          $('.preview').append($('<img>').attr({// insert preview image
            src: e.target.result,
            id: "crop_img",
            title: data.files[0].name
          }));
          $('#crop_img').cropper() // initialize cropper on preview image
         };
       reader.readAsDataURL(data.files[0]);
       };

      lastData = data;
    },


    progressall: function (e, data) {
      var progress = parseInt(data.loaded / data.total * 100, 10);
      progressBar.css('width', progress + '%')
    },

    start: function (e) {
      submitButton.prop('disabled', true);

      progressBar.
        css('background', 'black').
        css('display', 'block').
        css('width', '0%').
        text("Loading...");
    },

    done: function(e, data) {
      submitButton.prop('disabled', false);
      progressBar.text("Uploading done");

      // extract key and generate URL from response
      var key   = $(data.jqXHR.responseXML).find("Key").text();
      var url   = '//' + form.data('host') + '/' + key;

      // create hidden field
      var input = $("<input />", { type:'hidden', name: fileInput.attr('name'), value: url })
      form.append(input);

      //delete submit event which is false
      $('form').off('submit');
      //and submit again
      $('.directUpload').submit();
    },

    fail: function(e, data) {
      submitButton.prop('disabled', false);

      progressBar.
        css("background", "red").
        text("Upload Failed!");
      }
    });
  });
});

我认为这是因为这些浏览器不支持 toBlob() 方法,然后,根据this article,我在我的 html 文件中包含了 canvas-to-blob.min.js。

但还是不行。

我也尝试了以下代码,而不是使用 toBlob() 方法(根据this article),它也不起作用......

//$('#crop_img').cropper('getCroppedCanvas').toBlob(function (blob){
       // lastData.files[0] = new File([blob], lastData.files[0].name);
        //lastData.originalFiles[0] = lastData.files[0];
        //lastData.submit();
 //     })
 
 //insetead of the code above, tried this...
      var canvas = $('#crop_img').cropper('getCroppedCanvas');
      var canvas_data = canvas.toDataURL();
      var blobData = dataURItoBlob(canvas_data);
      function dataURItoBlob(dataURI) {
         var binary = atob(dataURI.split(',')[1]);
         var array = [];
         for(var i = 0; i < binary.length; i++) {
             array.push(binary.charCodeAt(i));
         }
         return new Blob([new Uint8Array(array)], {type: 'image/jpeg'});
     }
     lastData.files[0] = new File([blobData], lastData.files[0].name);
     lastData.originalFiles[0] = lastData.files[0];
     lastData.submit();
   });

我完全不知所措....有人帮帮我吗...?

【问题讨论】:

    标签: javascript jquery html ios blob


    【解决方案1】:

    您可能应该通过 AJAX 将 canvasElement.toDataURL() 发送到像 PHP 这样的服务器语言,在那里您可以 file_put_contents('tempfile.png', $dataURLajaxResult),然后您将有一个可以发送的文件,无论如何。

    【讨论】:

    • 非常感谢您的回答!实际上我正在使用 Ruby on Rails,但那是一样的吗?我想直接将它发送到 s3,因为我的服务器(heroku)需要很长时间才能通过 RoR 上传......我想要做的是:devcenter.heroku.com/articles/…
    猜你喜欢
    • 1970-01-01
    • 2013-01-03
    • 1970-01-01
    • 1970-01-01
    • 2011-03-17
    • 2012-01-15
    • 2010-10-09
    • 2014-04-04
    • 1970-01-01
    相关资源
    最近更新 更多