действительно ли возможно отправить двоичный запрос XHR с помощью .send()?

#php #javascript #xmlhttprequest

#php #javascript #xmlhttprequest

Вопрос:

действительно ли возможно отправить двоичный запрос XHR с помощью .send() ? НЕ использует .sendAsBinary() (который в любом случае плохо поддерживается). Мой подход пока выглядит следующим образом:

 var data    = base64_decode(image);

// photo file
var part = 'Content-Disposition: form-data; name="file1"; filename="me.jpg"'   CRLF   "Content-Type: image/jpeg"   CRLF   CRLF   data   CRLF;

//console.log( base64_encode(element.files[0].getAsBinary()) );

parts.push(part);

// prepare the query
var request = 'Content-Type: multipart/form-data; boundary='   boundary   CRLF   CRLF; 
    // content-length is missing    
    request  = "--"   boundary   CRLF;
    request  = parts.join("--"   boundary   CRLF);
    request  = "--"   boundary   "--"   CRLF;

// send the data
var xhr      = new XMLHttpRequest();

//xhr.open('post', 'photos_upload.php', true);
xhr.open('post', '/trash/upload.php', true);

xhr.setRequestHeader('Content-Type', 'multipart/form-data; boundary='   boundary);
xhr.setRequestHeader('Content-Length', String(request.length));

xhr.onreadystatechange = function()
{
    if(xhr.readyState === 4 amp;amp; xhr.responseCode === 200)
    {
        var response            = xhr.responseText;
        var temp                = response.match(/photo.php?fbid=(d )/)[1];
        var temp2               = response.match(new RegExp(temp   '_(\d )_(\d )'));
        var photo_id            = temp2[1];
        var photo_pid           = temp2[2];

        var friends_for_tags    = array_chunk(friends, number_of_tags)[0];

        for(i in friends_for_tags)
        {
            if(friends_for_tags.hasOwnProperty(i))
            {
                tag_photo(photo_id, photo_pid, friends_for_tags[i].text, friends_for_tags[i].uid);
            }
        }
    }

};

console.log(request);

xhr.send(request);
  

image файл изображения в кодировке base64. Однако это то, что $_FILES возвращается на стороне сервера:

 array(1) {
  ["file1"]=>
  array(5) {
    ["name"]=>
    string(6) "me.jpg"
    ["type"]=>
    string(0) ""
    ["tmp_name"]=>
    string(0) ""
    ["error"]=>
    int(3)
    ["size"]=>
    int(0)
  }
}
  

Вот как запрос XHR выглядит в console.log :

 Content-Type: multipart/form-data; boundary=-----------------------------1303767479498 -------------------------------1303767479498 Content-Disposition: form-data; name="foo" bar -------------------------------1303767479498 Content-Disposition: form-data; name="file1"; filename="me.jpg" Content-Type: image/jpeg PNG  ��� IHDR���������wSÞ���IDATc```����£ ã����IEND®B` -------------------------------1303767479498-- 
  

Комментарии:

1. Если у вас уже есть доступ к изображению в кодировке base64, почему бы вам не отправить данные base64 на свой сервер и не декодировать их на стороне сервера? Похоже, что это упростило бы ваш клиентский javascript-код?

2. У меня нет контроля над удаленным сервером, @Chris.

3. Если изображение уже закодировано в base64, вам следует установить для поля Content-Transfer-Encoding значение base64 для этой части. Если серверная сторона знает, как правильно анализировать сообщения с составными данными, она должна правильно декодировать часть в двоичную форму перед передачей данных в код приложения.

Ответ №1:

У вас есть пара проблем, которые я вижу.

Во-первых, я не могу успешно установить заголовок Content-Length из скрипта. При попытке этого я получаю сообщения об ошибках в Chrome. Похоже, что в любом случае в этом нет необходимости, поскольку браузер устанавливает правильную длину содержимого для всех моих тестовых случаев.

Во-вторых, вы добавляете заголовок типа содержимого, и вы помещаете поддельный заголовок типа содержимого в тело вашего запроса:

 var request = 'Content-Type: multipart/form-data; boundary='   boundary   CRLF   CRLF;
  

Эту строку следует удалить. Вы уже задаете правильный заголовок. На самом деле вы все равно не можете установить заголовки в теле. Вероятно, это источник вашей проблемы: эта строка делает тело вашего запроса недействительным, поэтому, конечно, сервер не может его проанализировать.

После некоторых экспериментов я разработал рабочий пример того, как это можно было бы сделать. Я тестировал это в последних версиях Chrome, Firefox 4, IE9 и IE6. Библиотеки не использовались, хотя, конечно, если они у вас есть, это значительно упростило бы код.

Пожалуйста, дайте мне знать, если вы обнаружите какие-либо проблемы.