YouTube Data API无代码变更突发视频上传getHeaderLine()报错
问题背景
使用YouTube Data API实现的频道视频上传功能已稳定运行数年,在代码数月未修改、系统长期未部署新版本、vendor目录下第三方依赖完全无变动的情况下,功能突然抛出如下错误:
Call to undefined method Google\Service\YouTube\Video::getHeaderLine()
当前使用的分块上传代码如下(非当前开发人员编写,不排除写法过时、不符合官方使用规范的可能):
$media = new Google_Http_MediaFileUpload($client, $request, $mimeType, null, true, $chunkSizeBytes); $media->setFileSize(filesize($filePath)); // 分块读取媒体文件完成上传 $status = false; $handle = fopen($filePath, "rb"); while (!$status && !feof($handle)) { $chunk = fread($handle, $chunkSizeBytes); $status = $media->nextChunk($chunk); } fclose($handle); return $status;
错误触发时的部分堆栈跟踪信息如下:
Call to undefined method Google\Service\YouTube\Video::getHeaderLine() {"file":"/var/www/release/20220602115951/vendor/google/apiclient/src/Http/MediaFileUpload.php","line":310,"code":0,"trace":[{"file":"/var/www/release/20220602115951/vendor/google/apiclient/src/Http/MediaFileUpload.php","line":289,"function":"fetchResumeUri","class":"Google\\Http\\MediaFileUpload"}, {"file":"/var/www/release/20220602115951/vendor/google/apiclient/src/Http/MediaFileUpload.php","line":126,"function":"getResumeUri","class":"Google\\Http\\MediaFileUpload"}, {"file":"/var/www/release/20220602115951/modules/you_tube/src/Services/YouTube.php","line":93,"function":"nextChunk","class":"Google\\Http\\MediaFileUpload"}, {"file":"/var/www/release/20220602115951/modules/you_tube/src/Services/YouTube.php","line":573,"function":"uploadVideoFile","class":"YouTube\\Services\YouTube"}
问题根因
- 参数类型不匹配:
Google\Http\MediaFileUpload构造函数要求第二个参数传入实现了Psr\Http\Message\RequestInterface的HTTP请求实例,只有这类HTTP消息对象才带有getHeaderLine()方法。从报错可以判断,当前代码传入的$request实际是Google\Service\YouTube\Video资源对象,该类作为API数据模型,不存在getHeaderLine()方法,调用时直接触发致命错误。 - 隐式兼容失效:当前使用的google/apiclient版本较老,旧版本中非规范写法存在偶然的兼容空间,但近期YouTube Data API侧的接口流程、鉴权返回逻辑调整,打破了这种非预期的兼容状态,和本地代码、依赖是否改动没有直接关系。
- 旧类名兼容风险:代码中使用的
Google_Http_MediaFileUpload是版本迁移期的别名类,在边缘场景下容易出现类型加载、判断逻辑异常。
修复方案
- 修正上传请求的生成逻辑
生成用于断点续传的请求对象时,不要直接执行insert接口拿Video返回值,需要在调用insert方法时指定uploadType参数为resumable,拿到原始HTTP请求对象后再传入MediaFileUpload类,修正后的参考代码如下:// 构造视频资源模型,和原有业务逻辑一致 $video = new Google\Service\YouTube\Video(); // 自行填充snippet、status等视频属性 // $video->setSnippet(...); // $video->setStatus(...); // 关键:指定uploadType为resumable,拿到待发送的请求对象,不要直接接收Video实例 $request = $youtube->videos->insert( 'status,snippet', $video, ['uploadType' => 'resumable'] ); // 初始化上传类,建议使用带命名空间的正式类名替代旧别名 $media = new Google\Http\MediaFileUpload( $client, $request, $mimeType, null, true, $chunkSizeBytes ); $media->setFileSize(filesize($filePath)); // 原有分块读取上传逻辑无需改动 $status = false; $handle = fopen($filePath, "rb"); while (!$status && !feof($handle)) { $chunk = fread($handle, $chunkSizeBytes); $status = $media->nextChunk($chunk); } fclose($handle); return $status; - 快速校验排查
先定位$request变量的赋值逻辑,确认传入MediaFileUpload构造函数的变量类型:如果是直接将$youtube->videos->insert()的执行结果赋值给$request,就会拿到Video对象触发报错,调整为上述传参方式拿到请求对象即可。 - 依赖版本优化
执行composer show google/apiclient确认当前客户端版本,如果版本低于2.12.0,建议升级到2.x分支的最新稳定版,2.x版本不存在破坏性变更,升级后可修复旧版本中存在的上传流程兼容bug,适配API侧的最新逻辑。
内容的提问来源于stack exchange,提问作者Chris Darby
相关产品推荐
相关产品推荐

