获得';Multipart必须具有Atom和媒体部件';尝试将带有元数据的照片上载到Picasa时出错


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

我有下面的代码,它试图将带有元数据的图像上传到Picasa网络相册。

如果我取出元数据,直接执行内容类型:image/jpegPOST请求,下面的代码就可以上传图像。

$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错误消息。

以下是我发送的标题:

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

我在这里做错了什么?

因此,事实证明Content-Length问题。

这个来自YouTube API文档的小片段解决了这个问题

要计算正确的ContentLength,需要计算POST请求的完整字符串长度。但是,除了XML组件和文件二进制文件外,直接上传请求还定义了一个边界字符串,用于分隔请求的不同部分。因此内容长度的计算需要考虑XML和文件二进制文件以及插入的边界字符串和换行符的大小

我将Content-Length设置为二进制图像数据和XML的长度之和。我没有数换行符或边界标记。

所以这个比特

'Content-Length: ' . $dataLength

需要更改为

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