Blob in FormData is null

筅森魡賤 提交于 2019-12-11 02:05:18

问题


I'm trying to send created photo in android via ajax via remote API. I'm using Camera Picture Background plugin.

Photo is created properly, I'm getting it via ajax GET request and encode it to base64 format. In debugging tool I can see image itself through GET request log.

Next I parse it base64 to Blob and try to attach it to FormData:

var fd = new FormData();
fd.append('photo', blobObj);
$.ajax({
  type: 'POST',
  url: 'myUrl',
  data: fd,
  processData: false,
  contentType: false
}).done(function(resp){
  console.log(resp);
}). [...]

But when I send the FormData I see in debugger that FormData in request equals to: {photo: null}.

Btw. if I try to console.log my blobObj earlier, I see it is a blob, with its size, type properties and slice method - why it becomes a null after appending to FormData?

EDIT:

console.log(blobObj); gives:

Blob {type: "image/jpeg", size: 50778, slice: function}

EDIT2 - STEP BY STEP CODE:

I have url to local image, let's assume it is stored in imagePath variable.

First, I get this file and parse it to base64:

function base64Encode(){
  var CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
  var out = "", i = 0, len = str.length, c1, c2, c3;

  while (i < len) {
    c1 = str.charCodeAt(i++) & 0xff;
    if (i == len) {
      out += CHARS.charAt(c1 >> 2);
      out += CHARS.charAt((c1 & 0x3) << 4);
      out += "==";
      break;
    }
    c2 = str.charCodeAt(i++);
    if (i == len) {
      out += CHARS.charAt(c1 >> 2);
      RS.charAt(((c1 & 0x3)<< 4) | ((c2 & 0xF0) >> 4));
      out += CHARS.charAt((c2 & 0xF) << 2);
      out += "=";
      break;
    }
    c3 = str.charCodeAt(i++);
    out += CHARS.charAt(c1 >> 2);
    out += CHARS.charAt(((c1 & 0x3) << 4) | ((c2 & 0xF0) >> 4));
    out += CHARS.charAt(((c2 & 0xF) << 2) | ((c3 & 0xC0) >> 6));
    out += CHARS.charAt(c3 & 0x3F);
  }
  return out;
} 

function getFile(fileData){
  var dfd = new $.Deferred();
  $.ajax({
    type: 'GET',
    url: fileData,
    mimeType: "image/jpeg; charset=x-user-defined"
  }).done(function(resp){
    var file = base64Encode(resp);

    dfd.resolve(file);
  }).fail(function(err){
    console.warn('err', err);
    dfd.resolve();
  });

  return dfd.promise();
};

$.when(getFile(imagePath)).then(function(resp){
    var fd = new FormData();

    resp = 'data:image/jpeg;base64,' + resp;

    var imgBlob = new Blob([resp], {type : 'image/jpeg'});

    fd.append('photo', img, 'my_image.jpg');

    $.ajax({
      type: 'POST',
      url: 'myUrlToUploadFiles',
      data: fd,
      processData: false,
      contentType: false
    }).done(function(resp){
      console.log(resp);
    }). [...]
});

回答1:


I've not done this recently, but this works with me. I hope it also works with you:

function getBase64ImageByURL(url) {
  var dfd = new $.Deferred();
  var xhr = new XMLHttpRequest();
  xhr.responseType = 'blob';
  xhr.onload = function() {
    var reader = new FileReader();
    reader.onloadend = function() {
      dfd.resolve(reader.result);
    }
    reader.readAsDataURL(xhr.response);
  };
  xhr.open('GET', url);
  xhr.send();
  return dfd.promise();
}

function base64ToBlob(base64Image,toMimeType) {
  var byteCharacters = atob(base64Image.replace('data:'+toMimeType+';base64,',''));
  var byteNumbers = new Array(byteCharacters.length);
  for (var i = 0; i < byteCharacters.length; i++) {
    byteNumbers[i] = byteCharacters.charCodeAt(i);
  }
  var byteArray = new Uint8Array(byteNumbers);
  var blob = new Blob([byteArray], {
    type: toMimeType
  });
  return blob;
}



var imageUrl = "https://upload.wikimedia.org/wikipedia/commons/4/49/Koala_climbing_tree.jpg";

getBase64ImageByURL(imageUrl).then(function(base64Image){
  var blob = base64ToBlob(base64Image,'image/jpeg');
  var fd = new FormData();
  fd.append('file', blob, 'my_image.jpg');
  $.ajax({
    url: 'http://your_host/uploads/testupload.php',
    data: fd,
    type: 'POST',
    contentType: false,
    processData: false,
    success:function(res){
      console.log(res);
    },
    error:function(err){
      console.log(err);
    }
  })
});

On server-side(testupload.php):

<?php

    if ( 0 < $_FILES['file']['error'] ) {
        echo 'Error: ' . $_FILES['file']['error'] . '<br>';
    }
    else {
        $result = move_uploaded_file($_FILES['file']['tmp_name'], $_SERVER["DOCUMENT_ROOT"].$_SERVER["BASE"].'/uploads/'.'my_image.jpg');
        var_dump("image uploaded: ".$result);
    }

?>

It might be necessary to modify some read/write-permissions on a directory before move_uploaded_file succeeds in moving the uploaded image to this directory.

The function getBase64ImageByURL could already return a blob-object but by returning a base64-image you can show an user this image in a html-image-tag before uploading it for instance.


If there is no need to show an user that image, then you can also shorten all steps:

function getBlobImageByURL(url) {
  var dfd = new $.Deferred();
  var xhr = new XMLHttpRequest();
  xhr.responseType = 'blob';
  xhr.onload = function() {
    dfd.resolve(xhr.response);
  };
  xhr.open('GET', url);
  xhr.send();
  return dfd.promise();
}

getBlobImageByURL(imageUrl).then(function(imageBlob){
  var fd = new FormData();
  fd.append('file', imageBlob, 'my_image.jpg');
  console.log(fd.get('file'));// File-object 
  $.ajax({
    url: 'http://your_host/uploads/testupload.php',
    data: fd,
    type: 'POST',
    contentType: false,
    processData: false,
    success:function(res){
      console.log(res);
    },
    error:function(err){
      console.log(err);
    }
  })
});

references to both modified functions base64ToBlob and getBase64ImageByURL



来源:https://stackoverflow.com/questions/41398692/blob-in-formdata-is-null

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!