2

所以我设法建立了 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); }

我得到的错误:HTTP/1.1 400 Bad Request Server: HTTP Upload Server Built on May 7 2012 18:16:42 (1336439802) Content-Type: text/html; charset=UTF-8 X-GUploader-UploadID: AEnB2Uq7cHcf6rS4bcamu18ChAF3gnKJqsF6U_dk2qB4WR9GhAoTL_-iUejitgead-Gh-1fpJcke1z68TAxoopS2vYiGmCW69A Date: Thu, 10 May 2012 11:55:24 GMT Pragma: no-cache Expires: Fri, 01 Jan 1990 00:00:00 GMT Cache -控制:无缓存,无存储,必须重新验证内容长度:15 连接:关闭

无效的请求

谢谢大家!

4

1 回答 1

1

我注意到几件事:对 POST 和 Host 标头进行硬编码是一种糟糕的形式,因为 curl 会自动为您处理它们。我怀疑部分问题是在 $videoData 和最后一个边界标记之间插入了回车/换行符。这将被解释为视频文件的一部分。您所需要的只是换行符作为行分隔符。也许回车会使视频文件无效?

也许 curl_setopt($ch, CURLOPT_VERBOSE, true) 会提供一些照明。

这对我有用(在 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;
    }
于 2012-08-31T21:05:03.120 回答