PHP API Youtube上传,例外:无法启动可恢复的上传,上传必须发送到上传URL [英] PHP API Youtube Uploads, exception: Failed to start the resumable upload, upload must be sent to the upload URL

查看:151
本文介绍了PHP API Youtube上传,例外:无法启动可恢复的上传,上传必须发送到上传URL的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试构建一个将视频上传到YouTube的服务器应用程序。在我的服务器应用程序中,用户可以直接将视频上传到我的YouTube频道以将其公开。



  1. 我的应用程序的客户端部分获取视频并上传它到我的服务器。

  2. 然后我的服务器使用YouTube API将视频上传到我的YouTube频道。 b
    $ b

    为了完成这项工作,我创建了一个虚拟Web应用程序,它可以捕获生成的刷新标记,并将它存储在 key.txt 文件中。

      {access_token:MYTOKEN,token_type:承载者,expires_in:3600,created:1435654774} 

    upload_video.php 脚本会自动更新<$如果 access_token 过期,c $ c>key.txt文件。这是 upload_video.php 的代码:

      $ key = file_get_contents ( 'key.txt'); 

    $ application_name ='YouTube_Upload';
    $ client_secret ='MY_CLIENT_SECRET';
    $ client_id ='MY_CLIENT_ID';
    $ scope = array('https://www.googleapis.com/auth/youtube.upload','https://www.googleapis.com/auth/youtube','https:// www。 googleapis.com/auth/youtubepartner');

    $ videoPath =Test.f4v;
    $ videoTitle =教程视频;
    $ videoDescription =关于如何上传到YouTube的视频教程;
    $ videoCategory =22;
    $ videoTags = array(youtube,tutorial);

    尝试{
    //客户端初始化
    $客户端=新建Google_Client();
    $ client-> setApplicationName($ application_name);
    $ client-> setClientId($ client_id);
    $ client-> setAccessType('offline');
    $ client-> setAccessToken($ key);
    $ client-> setScopes($ scope);
    $ client-> setClientSecret($ client_secret);

    if($ client-> getAccessToken()){

    / **
    *检查访问令牌是否已过期。如果是这样,请获取一个新文件并将其保存以备将来使用。
    * /
    if($ client-> isAccessTokenExpired()){
    $ newToken = json_decode($ client-> getAccessToken());
    $ client-> refreshToken($ newToken-> refresh_token);
    file_put_contents('key.txt',$ client-> getAccessToken());
    }

    $ youtube =新Google_Service_YouTube($ client);

    //创建一个包含标题,描述,标签和类别ID的snipet
    $ snippet = new Google_Service_YouTube_VideoSnippet();
    $ snippet-> setTitle($ videoTitle);
    $ snippet-> setDescription($ videoDescription);
    $ snippet-> setCategoryId($ videoCategory);
    $ snippet-> setTags($ videoTags);

    //创建隐私状态的视频状态。选项是公开,私人和不公开。
    $ status = new Google_Service_YouTube_VideoStatus();
    $ status-> setPrivacyStatus('unlisted');

    //创建一个带有片段和状态的YouTube视频
    $ video = new Google_Service_YouTube_Video();
    $ video-> setSnippet($ snippet);
    $ video-> setStatus($ status);

    //每个数据块的大小(以字节为单位)。将其设置得更高会导致更快的上传(更少的块,
    //用于可靠的连接)。将它设置得更低会导致更好的恢复(细粒度块)
    $ chunkSizeBytes = 1 * 1024 * 1024;

    //将defer标志设置为true,告诉客户端返回一个可以被称为
    //的请求 - > execute();而不是立即进行API调用。
    $ client-> setDefer(true);

    //创建一个请求API的videos.insert方法来创建和上传视频。
    $ insertRequest = $ youtube-> videos-> insert(status,snippet,$ video);

    //为可恢复的上传创建一个MediaFileUpload对象。
    $ media = new Google_Http_MediaFileUpload(
    $ client,
    $ insertRequest,
    'video / *',
    null,
    true,
    $ chunkSizeBytes
    );
    $ media-> setFileSize(filesize($ videoPath));

    //读取媒体文件并按块分块上传。
    $ status = false;
    $ handle = fopen($ videoPath,rb);
    while(!$ status&&!feof($ handle)){
    $ chunk = fread($ handle,$ chunkSizeBytes);
    $ status = $ media-> nextChunk($ chunk);
    }

    fclose($ handle);
    $ b / **
    *如果($ status-> status ['uploadStatus'] =='uploaded')视频已成功上传
    * /
    ) {
    //为成功上传而执行的操作
    // ......
    }

    //如果想在文件之后进行其他调用上传,将setDefer设置回false
    $ client-> setDefer(true);

    } else {
    // @TODO记录错误
    echo'创建客户端时出现问题';
    }

    } catch(Google_Service_Exception $ e){
    打印Google_Service_Exception。$ e-> getCode()。 message is。$ e-> getMessage();
    printStack trace is。$ e-> getTraceAsString();
    } catch(Exception $ e){
    打印Exception。$ e-> getCode()。 message is。$ e-> getMessage();
    printStack trace is。$ e-> getTraceAsString();
    }

    脚本运行时,会引发此异常:

     异常0消息无法启动可恢复上载(HTTP 400:全局,上传必须发送到上传URL。重新发送此请求https://www.googleapis.com/upload/youtube/v3/videos?part=status,snippet&uploadType=resumable)堆栈跟踪为
    #0 D:\xampp\htdocs\youtube\\ \\ src\Google\Http\MediaFileUpload.php(136):Google_Http_MediaFileUpload-> getResumeUri()
    #1 D:\xampp\htdocs\youtube\resumable_upload.php(100): Google_Http_MediaFileUpload-> nextChunk('\x00\x00\x00\x1Cftypf4v \x00\x00\x00 ...')
    #2 {main}
    getResumeUri()
    (第281行)在

    > Google_Http_MediaFileUpload ,我有var转储来自google的响应

      Google_Http_Request对象

    [batc hHeaders:Google_Http_Request:private] => Array

    [Content-Type] => application / http
    [Content-Transfer-Encoding] =>二进制
    [MIME-Version] => 1.0


    [queryParams:protected] =>数组

    [part] =>状态,片段
    [uploadType] =>可恢复


    [requestMethod:protected] => ; POST
    [requestHeaders:protected] =>数组

    [content-type] => application / json; charset = UTF-8
    [authorization] =>承载XXXXXXXXXXXXXXXX
    [content-length] => ; 187
    [x-upload-content-type] => video / *
    [x-upload-content-length] => 10201286
    [expect] =>


    [baseComponent:protected] => https://www.googleapis.com//upload
    [path:protected] => / youtube / v3 / videos
    [postBody:protected] => {snippet:{categoryId:22,description:关于如何上传到YouTube的视频教程,tags:[youtube,tutorial],title:A教程视频},status:{privacyStatus:unlisted}}
    [userAgent:protected] =>
    [canGzip:protected] =>
    [responseHttpCode:protected] => 400
    [responseHeaders:protected] => Array

    [x-guploader-uploadid] => XXXXXXXXXXXXXXXXXXXXXXXXXX
    [位置] => https://www.googleapis.com/upload/youtube/v3/videos?part = status,snippet& uploadType = resumable
    [vary] => Origin
    X-Origin
    [content-type] => application / json; charset = UTF-8
    [content-length] => 468
    [date] => 2015年7月10日星期五09:54:30 GMT
    [server] => UploadServer
    [alternate-protocol ] => 443:quic,p = 1


    [responseBody:protected] => {
    error:{
    errors:[
    {
    domain:global,
    reason:wrongUrlForUpload,
    消息:必须将上传内容发送到上传网址。请将此请求重新发送到https://www.googleapis.com/upload/youtube/v3/videos?part=status,snippet&uploadType=resumable
    }
    ],
    code:400,
    message:上传文件必须发送至上传网址,重新发送至https:// www .googleapis.com / upload / youtube / v3 / videos?part = status,snippet& uploadType = resumable
    }
    }

    [expectedClass:protected] => Google_Service_YouTube_Video
    [expectedRaw:protected] =>
    [accessKey] =>

    有什么不对?
    感谢任何帮助,并对错误的英语感到抱歉。

    解决方案

    这似乎是PHP Client Library Google API。转到GOOGLE_LIB_PATH / Http / MediaFileUpload.php并替换此行:

      $ this-> request-> setBaseComponent($ base /'upload'); 

    有了这个:

      $ this-> request-> setBaseComponent($ base。'upload'); 

    重试并分享结果。我遇到了Google Pubsub API的类似问题,其中由库设置的API路径不正确。


    I'm trying to build a server application for uploading videos to YouTube. In my server application, the user can upload a video directly to my YouTube channel to make it public.

    1. The client part of my application acquires the video and uploads it to my server.
    2. My server then uses YouTube API to upload the video to my YouTube channel.

    To make this work, I created a dummy Web Application that can capture the refresh token generated and I have stored it in a key.txt file

    {"access_token":"MYTOKEN","token_type":"Bearer","expires_in":3600,"created":1435654774}
    

    The upload_video.php script will automatically update "key.txt" file if access_token is out of date. This is the code from upload_video.php:

    $key = file_get_contents('key.txt');
    
    $application_name = 'YouTube_Upload'; 
    $client_secret    = 'MY_CLIENT_SECRET';
    $client_id        = 'MY_CLIENT_ID';
    $scope            = array('https://www.googleapis.com/auth/youtube.upload', 'https://www.googleapis.com/auth/youtube', 'https://www.googleapis.com/auth/youtubepartner');
    
    $videoPath        = "Test.f4v";
    $videoTitle       = "A tutorial video";
    $videoDescription = "A video tutorial on how to upload to YouTube";
    $videoCategory    = "22";
    $videoTags        = array("youtube", "tutorial");
    
    try{
        // Client init
        $client = new Google_Client();
        $client->setApplicationName($application_name);
        $client->setClientId($client_id);
        $client->setAccessType('offline');
        $client->setAccessToken($key);
        $client->setScopes($scope);
        $client->setClientSecret($client_secret);
    
        if ($client->getAccessToken()) {
    
            /**
             * Check to see if access token has expired. If so, get a new one and save it to file for future use.
             */
            if($client->isAccessTokenExpired()) {
                $newToken = json_decode($client->getAccessToken());
                $client->refreshToken($newToken->refresh_token);
                file_put_contents('key.txt', $client->getAccessToken());
            }
    
            $youtube = new Google_Service_YouTube($client);
    
            // Create a snipet with title, description, tags and category id
            $snippet = new Google_Service_YouTube_VideoSnippet();
            $snippet->setTitle($videoTitle);
            $snippet->setDescription($videoDescription);
            $snippet->setCategoryId($videoCategory);
            $snippet->setTags($videoTags);
    
            // Create a video status with privacy status. Options are "public", "private" and "unlisted".
            $status = new Google_Service_YouTube_VideoStatus();
            $status->setPrivacyStatus('unlisted');
    
            // Create a YouTube video with snippet and status
            $video = new Google_Service_YouTube_Video();
            $video->setSnippet($snippet);
            $video->setStatus($status);
    
            // Size of each chunk of data in bytes. Setting it higher leads faster upload (less chunks,
            // for reliable connections). Setting it lower leads better recovery (fine-grained chunks)
            $chunkSizeBytes = 1 * 1024 * 1024;
    
            // Setting the defer flag to true tells the client to return a request which can be called
            // with ->execute(); instead of making the API call immediately.
            $client->setDefer(true);
    
            // Create a request for the API's videos.insert method to create and upload the video.
            $insertRequest = $youtube->videos->insert("status,snippet", $video);
    
            // Create a MediaFileUpload object for resumable uploads.
            $media = new Google_Http_MediaFileUpload(
                $client,
                $insertRequest,
                'video/*',
                null,
                true,
                $chunkSizeBytes
            );
            $media->setFileSize(filesize($videoPath));
    
            // Read the media file and upload it chunk by chunk.
            $status = false;
            $handle = fopen($videoPath, "rb");
            while (!$status && !feof($handle)) {
                $chunk = fread($handle, $chunkSizeBytes);
                $status = $media->nextChunk($chunk);
            }
    
            fclose($handle);
    
            /**
             * Video has successfully been upload
             */
            if ($status->status['uploadStatus'] == 'uploaded') {
                // Actions to perform for a successful upload
                // ......
            }
    
            // If want to make other calls after the file upload, set setDefer back to false
            $client->setDefer(true);
    
        } else{
            // @TODO Log error
            echo 'Problems creating the client';
        }
    
    } catch(Google_Service_Exception $e) {
        print "Google_Service_Exception ".$e->getCode(). " message is ".$e->getMessage();
        print "Stack trace is ".$e->getTraceAsString();
    }catch (Exception $e) {
        print "Exception ".$e->getCode(). " message is ".$e->getMessage();
        print "Stack trace is ".$e->getTraceAsString();
    }
    

    When the script runs, it raise this exception:

    Exception 0 message is Failed to start the resume-able upload (HTTP 400: global, Uploads must be sent to the upload URL. Re-send this request to https://www.googleapis.com/upload/youtube/v3/videos?part=status,snippet&uploadType=resumable)Stack trace is 
    #0 D:\xampp\htdocs\youtube\src\Google\Http\MediaFileUpload.php(136): Google_Http_MediaFileUpload->getResumeUri()
    #1 D:\xampp\htdocs\youtube\resumable_upload.php(100): Google_Http_MediaFileUpload->nextChunk('\x00\x00\x00\x1Cftypf4v \x00\x00\x00...')
    #2 {main}
    

    exception raise on getResumeUri() (line 281) in Google_Http_MediaFileUpload, i have var dump the response from google

    Google_Http_Request Object
    (
        [batchHeaders:Google_Http_Request:private] => Array
            (
                [Content-Type] => application/http
                [Content-Transfer-Encoding] => binary
                [MIME-Version] => 1.0
            )
    
        [queryParams:protected] => Array
            (
                [part] => status,snippet
                [uploadType] => resumable
            )
    
        [requestMethod:protected] => POST
        [requestHeaders:protected] => Array
            (
                [content-type] => application/json; charset=UTF-8
                [authorization] => Bearer XXXXXXXXXXXXXXXX
                [content-length] => 187
                [x-upload-content-type] => video/*
                [x-upload-content-length] => 10201286
                [expect] => 
            )
    
        [baseComponent:protected] => https://www.googleapis.com//upload
        [path:protected] => /youtube/v3/videos
        [postBody:protected] => {"snippet":{"categoryId":"22","description":"A video tutorial on how to upload to YouTube","tags":["youtube","tutorial"],"title":"A tutorial video"},"status":{"privacyStatus":"unlisted"}}
        [userAgent:protected] => 
        [canGzip:protected] => 
        [responseHttpCode:protected] => 400
        [responseHeaders:protected] => Array
            (
                [x-guploader-uploadid] => XXXXXXXXXXXXXXXXXXXXXXXXXX
                [location] => https://www.googleapis.com/upload/youtube/v3/videos?part=status,snippet&uploadType=resumable
                [vary] => Origin
    X-Origin
                [content-type] => application/json; charset=UTF-8
                [content-length] => 468
                [date] => Fri, 10 Jul 2015 09:54:30 GMT
                [server] => UploadServer
                [alternate-protocol] => 443:quic,p=1
            )
    
        [responseBody:protected] => {
     "error": {
      "errors": [
       {
        "domain": "global",
        "reason": "wrongUrlForUpload",
        "message": "Uploads must be sent to the upload URL. Re-send this request to https://www.googleapis.com/upload/youtube/v3/videos?part=status,snippet&uploadType=resumable"
       }
      ],
      "code": 400,
      "message": "Uploads must be sent to the upload URL. Re-send this request to https://www.googleapis.com/upload/youtube/v3/videos?part=status,snippet&uploadType=resumable"
     }
    }
    
        [expectedClass:protected] => Google_Service_YouTube_Video
        [expectedRaw:protected] => 
        [accessKey] => 
    )
    

    What is wrong? Thanks for any help and sorry for bad English.

    解决方案

    This seems to be a problem with PHP Client Library of Google API. Go to GOOGLE_LIB_PATH/Http/MediaFileUpload.php and replace this line:

    $this->request->setBaseComponent($base . '/upload'); 
    

    With this one:

    $this->request->setBaseComponent($base . 'upload'); 
    

    Try again and share the results. I faced a similar problem with Google Pubsub API where API path set by library was incorrect.

    这篇关于PHP API Youtube上传,例外:无法启动可恢复的上传,上传必须发送到上传URL的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆