Getting 'Multipart must have Atom and media part' error when trying to upload a photo with metadata to Picasa

微笑、不失礼 提交于 2019-12-13 18:43:15

问题


I have the following code which is attempting to upload an image with metadata to a Picasa web album.

The code below works for uploading the image if I take out the metadata and just do a straight Content-Type: image/jpeg POST request.

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

The issue is that I keep getting back a 400 Bad Request: Multipart must have Atom and media part error message.

Here are the headers I'm sending:

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
)

And here's what the POST request body looks like:

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--

I think I have the line breaks correctly placed in the POST body but I'm not 100% sure. I'm also wondering if I've calculated the Content-Length correctly.

What am I doing wrong here?


回答1:


So, it turns out that it was a problem with the Content-Length.

This little snippet from the YouTube API docs solved it.

To calculate the proper Content-Length, you need to count the full string length of the POST request. However, in addition to the XML component and the file binary, a direct upload request also defines a boundary string that separates the different parts of the request. So the calculation of the Content-Length needs to account for the size of the XML and file binary as well as of the inserted boundary strings and newlines.

I was setting the Content-Length to the sum of the length of the binary image data and the XML. I wasn't counting newlines or boundary markers.

So this bit

'Content-Length: ' . $dataLength

needs to change to

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


来源:https://stackoverflow.com/questions/9841517/getting-multipart-must-have-atom-and-media-part-error-when-trying-to-upload-a

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