При попытке загрузить фотографию с метаданными в Picasa возникает ошибка «У нескольких частей должен быть Atom и медиа часть» - PullRequest
1 голос
/ 23 марта 2012

У меня есть следующий код, который пытается загрузить изображение с метаданными в веб-альбом Picasa.

Приведенный ниже код работает для загрузки изображения, если я извлекаю метаданные и просто выполняю прямую Content-Type: image / jpeg POST-запрос.

$albumUrl = "https://picasaweb.google.com/data/feed/api/user/$userId/albumid/$albumId";
$imgName = $_SERVER['DOCUMENT_ROOT'] . '/picasa/cute_baby_kitten.jpg';

$rawImgXml = '<entry xmlns="http://www.w3.org/2005/Atom">
              <title>plz-to-love-realcat.jpg</title>
              <summary>Real cat wants attention too.</summary>
              <category scheme="http://schemas.google.com/g/2005#kind"
                term="http://schemas.google.com/photos/2007#photo"/>
            </entry>';

$fileSize = filesize($imgName);
$fh = fopen($imgName, 'rb');
$imgData = fread($fh, $fileSize);
fclose($fh);

$dataLength = strlen($rawImgXml) + $fileSize;
$data = "";
$data .= "\nMedia multipart posting\n";
$data .= "--P4CpLdIHZpYqNn7\n";
$data .= "Content-Type: application/atom+xml\n\n";
$data .= $rawImgXml . "\n";
$data .= "--P4CpLdIHZpYqNn7\n";
$data .= "Content-Type: image/jpeg\n\n";
$data .= $imgData . "\n";
$data .= "--P4CpLdIHZpYqNn7--";

$header = array('GData-Version:  2', $authHeader, 'Content-Type: multipart/related;boundary=P4CpLdIHZpYqNn7', 'Content-Length: ' . $dataLength, 'MIME-version: 1.0');

$ret = "";
$ch  = curl_init($albumUrl);
$options = array(
        CURLOPT_SSL_VERIFYPEER=> false,
        CURLOPT_POST=> true,
        CURLOPT_RETURNTRANSFER=> true,
        CURLOPT_HEADER=> true,
        CURLOPT_FOLLOWLOCATION=> true,
        CURLOPT_POSTFIELDS=> $data,
        CURLOPT_HTTPHEADER=> $header
    );
curl_setopt_array($ch, $options);
$ret = curl_exec($ch);
curl_close($ch);

Проблема в том, что я получаю сообщение об ошибке 400 Bad Request: Multipart must have Atom and media part.

Вот заголовки, которые я 'm отправка:

Array
(
    [0] => GData-Version:  2
    [1] => Authorization:  GoogleLogin auth="THISISAVALIDAUTHCODE"
    [2] => Content-Type: multipart/related;boundary=P4CpLdIHZpYqNn7
    [3] => Content-Length: 179951
    [4] => MIME-version: 1.0
)

И вот как выглядит тело POST-запроса:

Media multipart posting
--P4CpLdIHZpYqNn7
Content-Type: application/atom+xml

<entry xmlns="http://www.w3.org/2005/Atom">
              <title>plz-to-love-realcat.jpg</title>
              <summary>Real cat wants attention too.</summary>
              <category scheme="http://schemas.google.com/g/2005#kind"
                term="http://schemas.google.com/photos/2007#photo"/>
            </entry>
--P4CpLdIHZpYqNn7
Content-Type: image/jpeg

IMAGE DATA GOES HERE
--P4CpLdIHZpYqNn7--

Я думаю, что у меня правильные разрывы строк в теле POST, но я не на 100% конечно.Мне также интересно, правильно ли я вычислил Content-Length.

Что я здесь не так делаю?

1 Ответ

0 голосов
/ 23 марта 2012

Итак, получается, что было проблемой с Content-Length.

Этот небольшой фрагмент из Документов YouTube API решил эту проблему.

Чтобы рассчитать правильную Content-Length, вам нужно посчитать полную длину строки запроса POST. Однако, в дополнение к компоненту XML и двоичному файлу, запрос прямой загрузки также определяет граничную строку, которая разделяет различные части запроса. Таким образом, вычисление Content-Length должно учитывать размер XML и двоичного файла, а также вставленных граничных строк и строк новой строки .

Я устанавливал Content-Length на сумму длины данных двоичного изображения и XML. Я не считал символы новой строки или границы.

Итак, этот бит

'Content-Length: ' . $dataLength

необходимо изменить на

'Content-Length: ' . strlen($data)
...