2016-12-30 5 views
1

Я пытаюсь отправить созданную фотографию в android через ajax через удаленный API. Я использую плагин Camera Picture Background.Blob in FormData is null

Фото создано правильно, я получаю его через 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 раньше, я вижу это a blob, с его размером, свойствами типа и методом среза - почему он становится нулевым после добавления к FormData?

EDIT:

console.log(blobObj); дает:

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

edit2 - Пошаговый КОД:

У меня есть URL для локального изображения, давайте предположим, что он хранится в imagePath переменной.

Во-первых, я получаю этот файл и разобрать его в base64:

function base64Encode(){ 
    var CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz/"; 
    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

Make blob как this 'var blob = new Blob ([payLoad], {type: 'image/png'});' – Viney

+0

На этот раз я получаю сообщение об ошибке: 'Загруженный вами файл был либо не изображение или поврежденное изображение. – mrmnmly

+1

Как вы преобразовали это base64-изображение в blob?Я использую filereader и его метод readAsArrayBuffer как первый параметр для конструктора blob. И использование имени файла может также помочь [здесь] (http://stackoverflow.com/questions/6664967/how-to-give-a-blob-uploaded-as-formdata-a-file-name) – Blauharley

ответ

1

Я не сделал это в последнее время, но это работает со мной. Я надеюсь, что он также работает с вами:

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 мог уже вернуть блоб-объект, но, возвращая base64-изображение, которое может показать пользователю это изображение в HTML-теге изображения перед загрузкой, например.


Если нет необходимости, чтобы показать пользователю, что изображение, то вы можете также сократить все этапы:

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

+0

Дайте мне знать, работает ли он с вами. – Blauharley

+0

привет, я изменил код, чтобы использовать холст, но все же, при отправке, formData 'file' (в моем случае -' фото') по-прежнему 'null'! :/btw. У меня нет доступа к серверному коду. – mrmnmly

+0

С холстом вы можете обрезать изображение перед загрузкой, но когда вам нужно изображение целиком, я предпочитаю filereader или объект XMLHttpRequest. Я применил более короткий вариант, который просто использует объект XMLHttpRequest. Я тестировал это с помощью хрома/FF и края. Обновите свой код, пожалуйста. – Blauharley