javascript - FormData 中的 Blob 为空

标签 javascript ajax cordova multipartform-data form-data

我正在尝试通过远程 API 通过 ajax 在 android 中发送创建的照片。我正在使用 Camera Picture Background 插件。

照片已正确创建,我通过 ajax GET 请求获取它并将其编码为 base64 格式。在调试工具中,我可以通过 GET 请求日志查看图像本身。

接下来我将它的 base64 解析为 Blob 并尝试将它附加到 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);
}). [...]

但是当我发送 FormData 时,我在调试器中看到请求中的 FormData 等于:{photo: null}

顺便说一句。如果我尝试 console.log 我的 blobObj ,我看到 它是 一个 blob,有它的大小、类型属性和切片方法 - 为什么它在附加到 FormData 后变为空值?

编辑:

console.log(blobObj); 给出:

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

EDIT2 - 分步代码:

我有本 map 片的 url,我们假设它存储在 imagePath 变量中。

首先,我得到这个文件并将其解析为 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);
    }). [...]
});

最佳答案

我最近没有这样做,但这对我有用。我希望它也适用于您:

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);
    }
  })
});

在服务器端(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);
    }

?>

move_uploaded_file 成功将上传的图像移动到该目录之前,可能需要修改目录的一些读/写权限。

getBase64ImageByURL 函数已经可以返回一个 blob 对象,但通过返回一个 base64 图像,您可以在上传之前在 html-image-tag 中向用户显示该图像。


如果不需要向用户显示该图像,那么您还可以缩短所有步骤:

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);
    }
  })
});

对两个修改函数的引用 base64ToBlob getBase64ImageByURL

关于javascript - FormData 中的 Blob 为空,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41398692/

相关文章:

c# - 存储/获取信息客户端的最佳方式

javascript - Apache Cordova 缺少 cordova.js

javascript - 如何创建一个 javascript 函数来输出对象列表以及对象属性列表?

javascript - 来自 2 个不同页面的 Codeigniter 3 多个 Ajax

ajax - 何时实现 Ajax 的最佳实践?

ios - Xcode 10 应用程序上传卡在 "negotiating connection..."

javascript - 使用 XmlHttpRequest 和纯 JavaScript 调用 WebMethods

jquery - 在 jQuery DataTables 中的 Ajax 请求后在 td 中添加 html 元素

android - phonegap-android 中的 Webintent 电子邮件?

authentication - 具有 HTTP 基本身份验证的 PhoneGap FileTransfer