【问题标题】:Youtube Oauth 2.0 API Videos Upload FailedYoutube Oauth 2.0 API 视频上传失败
【发布时间】:2012-05-21 11:16:08
【问题描述】:

所以我设法构建了 oauth 2.0 youtube 视频上传,但每次我上传视频时,我都会收到 HTTP 400 错误,请求无效。

但最奇怪的是,视频上传到 youtube 时出现:失败(上传中止)。

我没有使用任何框架,因为谷歌还没有任何 oauth 2.0,所以我自己构建了所有代码。

而且我确实设法发送了 cmets 和其他东西......唯一的问题是视频上传本身。

我的代码:

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-GUPLOODER-UNENB2UQ7CHCF6RS4BCAMU18CHAF3GNKJQSF6U_DK2QB4WR9GHAOTL_-IUEJITGEAD-GH-1FPJCCKE1Z68TAXOOPS2VYIGMCWW69A日期:THU,2012年5月11日11:55:24 GMT Pragma:No-Cache到期:FRI,20190 00:00 GMT缓存-控制:无缓存,无存储,必须重新验证内容长度:15 连接:关闭

无效请求

谢谢大家!

【问题讨论】:

    标签: php api oauth youtube


    【解决方案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;
        }
    

    【讨论】:

    • 现在我遇到了这个问题(使用你的代码):Malformed multipart post..... 这是什么意思?
    • 我认为错误是因为 $content 变量中的文本没有正确组装。我使用的是 Linux 主机,如果您使用的是 Windows 主机,则行尾不同,可能会导致问题。您是否确认 file_get_contents() 可以读取 $video_file 指向的文件?函数声明上方的注释中有一个链接,它有一个完整的 $content 应该是什么样子的示例,以及所需的标题。也许仔细比较它和你所拥有的会发现问题。
    • carl,我使用的是 debian 主机,所以操作系统不是问题 :) 我确认我正在获取文件的内容,一切都很好,就像你组装的功能一样。 ..这太奇怪了...
    • Avihay,也许当您复制/粘贴代码时,格式略有变化?有几个地方的行尾需要“背靠背”,标题需要在行的开头,没有尾随空格。希望对您有所帮助...
    猜你喜欢
    • 2019-03-15
    • 2015-12-28
    • 1970-01-01
    • 1970-01-01
    • 2015-11-19
    • 2014-05-25
    • 1970-01-01
    • 2023-03-15
    • 1970-01-01
    相关资源
    最近更新 更多