所以我设法构建了oauth 2.0 youtube视频上传,但是每次上传视频时,我都会收到带有无效请求的HTTP 400错误。
但最奇怪的是,视频正在上传到YouTube,同时有:失败(上传中止(。
我没有使用任何框架,因为谷歌还没有任何OAUTH 2.0,所以我自己构建了所有代码。
而且我确实设法发送了评论和东西......唯一的问题是视频上传本身。
我的代码:
public function uploadVideo($video, $title, $description, $category, $keywords) {
$url = 'http://uploads.gdata.youtube.com/feeds/api/users/FacebookDevelopersIL/uploads';
$boundary = uniqid();
$accessToken = $this->refreshAccessToken("13", "11313", 'REFRESHTOKEN');
$xmlString = "<?xml version='1.0'?><entry xmlns='http://www.w3.org/2005/Atom' xmlns:media='http://search.yahoo.com/mrss/' xmlns:yt='http://gdata.youtube.com/schemas/2007'><media:group><media:title type='plain'>".$title."</media:title><media:description type='plain'>".$description."</media:description> <media:category scheme='http://gdata.youtube.com/schemas/2007/categories.cat'>".$category."</media:category><media:keywords>".$keywords."</media:keywords></media:group></entry>";
$videoData = file_get_contents($video);
$headers = array(
'POST /feeds/api/users/FacebookDevelopersIL/uploads HTTP/1.1',
'Host: uploads.gdata.youtube.com',
'Authorization: Bearer '.$accessToken,
'GData-Version: 2',
'X-GData-Key: key='.YOUTUBE_SRM_DEVELOPER_KEY,
'Slug: IMG_0047.mp4',
'Content-Type: multipart/related; boundary='.$boundary,
'Content-Length:'.strlen($videoData),
'Connection: close'
);
$postData = "--".$boundary . "'r'n"
."Content-Type: application/atom+xml; charset=UTF-8'r'n'r'n"
.$xmlString . "'r'n"
."--".$boundary . "'r'n"
."Content-Type: video/mp4'r'n"
."Content-Transfer-Encoding: binary'r'n'r'n"
.$videoData . "'r'n"
."--".$boundary . "--";
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_HEADER, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 0);
$response = curl_exec($ch);
curl_close($ch);
Trace::dump($response); }
错误 im 得到: HTTP/1.1 400 错误请求服务器: HTTP 上传服务器 构建于 May 7 2012 18:16:42 (1336439802( 内容类型:文本/html; charset=UTF-8 X-GUploader-UploadID: AEnB2Uq7cHcf6rS4bcamu18ChAF3gnKJqsF6U_dk2qB4WR9GhAoTL_-iUejitgead-Gh-1fpJcke1z68TAxoopS2vYiGmCW69A 日期:2012 年 5 月 10 日星期四 11:55:24 GMT 杂注:无缓存 到期: 星期五, 01 一月 1990 00:00:00 GMT 缓存控制:无缓存、无存储、必须重新验证 内容长度:15 连接:关闭
无效请求
谢谢大家!
我注意到的几件事:硬编码 POST 和 Host 标头的形式很差,因为 curl 会自动为您处理它们。我怀疑部分问题是在$videoData和最后一个边界标记之间插入回车/换行。这将被解释为视频文件的一部分。您所需要的只是换行符作为行分隔符。也许回车使视频文件无效?
也许curl_setopt($ch,CURLOPT_VERBOSE,真的(会提供一些启发。
这对我有用(在 Linux 主机上(:
/*
** https://developers.google.com/youtube/2.0/developers_guide_protocol_direct_uploading
*/
private function send_to_youtube($video_file, $video_info) {
// Refresh access token
log_msg("Obtaining access token");
$response = http_post($this->config['token_url'], array(
'client_id' => $this->config['client_id'],
'client_secret' => $this->config['client_secret'],
'refresh_token' => $video_info->refresh_key,
'grant_type' => $this->config['grant_type']
));
if ($response['http_code'] != 200)
throw new Exception("Unable to obtain access token. ".print_r($response, true));
$authorization = json_decode($response['contents'], true);
// Build multi-part upload request
// api xml and then video file contents
$boundary = uniqid();
$location = '';
if ($video_info->latitude && $video_info->longitude)
$location = '
<georss:where>
<gml:Point>
<gml:pos>'. $video_info->latitude .' '. $video_info->longitude .'</gml:pos>
</gml:Point>
</georss:where>';
$content = '--'.$boundary.'
Content-Type: application/atom+xml; charset=UTF-8
<?xml version="1.0"?>
<entry xmlns="http://www.w3.org/2005/Atom"
xmlns:media="http://search.yahoo.com/mrss/"
xmlns:yt="http://gdata.youtube.com/schemas/2007"
xmlns:georss="http://www.georss.org/georss"
xmlns:gml="http://www.opengis.net/gml">
<media:group>
<media:title type="plain">'. $video_info->title .'</media:title>
<media:description type="plain">
'. $video_info->description .'
</media:description>
<media:category
scheme="http://gdata.youtube.com/schemas/2007/categories.cat">
'. $video_info->category .'
</media:category>
<media:keywords>'. implode(', ', $video_info->tags) .'</media:keywords>
</media:group>
'. $location .'
</entry>
--'.$boundary.'
Content-Type: '. $video_info->type .'
Content-Transfer-Encoding: binary
'.file_get_contents($video_file).'
--'.$boundary.'--';
$headers = array(
'Authorization: '.$authorization['token_type'].' '.$authorization['access_token'],
'GData-Version: 2',
'X-GData-Key: key='.$this->config['dev_key'],
'Slug: '.$video_info->filename,
'Content-Type: multipart/related; boundary="'.$boundary.'"',
'Content-Length: '.strlen($content),
'Connection: close'
);
// Upload video
log_msg("Sending video '{$video_info->title}', {$video_info->url}");
$ch = curl_init($this->config['upload_url']);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $content);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_HEADER, false);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 0);
$response = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if (!$http_code == 201) { // Something other than 'New Entry'
log_msg("Upload Failed: ".print_r($response, true));
return new SimpleXMLElement();
}
$entry = new SimpleXMLElement($response);
$yt_link = $entry->link[0]->attributes()->href;
log_msg("Upload Complete: ".$yt_link);
return $entry;
}