Я пытался загружать видео в API YouTube с помощью прямой загрузки. Я наконец взломал процесс OAuth, и у меня есть действующий токен. Мне действительно нужно сделать с YouTube только 2 вещи: аутентификация и загрузка. Я не просматриваю и не использую какие-либо другие функции. Пользователи загружают видео на этот сайт, а я отправляю их на YouTube для воспроизведения.

Мне кажется, что я прошел 80-90% пути самостоятельно, поэтому я не хочу отказываться от этого и использовать библиотеку Zend, которую предоставляет Google.

Проблема: когда я отправляю запрос, я получаю такой ответ:

HTTP/1.1 413 Request Entity Too Large
Content-Type: text/html; charset=UTF-8
Content-Length: 171
Date: Thu, 18 Apr 2013 18:33:22 GMT
Expires: Thu, 18 Apr 2013 18:33:22 GMT
Cache-Control: private, max-age=0
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block
Server: GSE
Connection: close

Если я включаю предупреждения, я также получаю предупреждение о сломанной трубе, которое, вероятно, является просто кодом, пытающимся загрузить данные через закрытое / отклоненное соединение.

Моя просьба такова:

POST /feeds/api/users/default/uploads HTTP/1.1 
Host: gdata.youtube.com Connection: close 
User-Agent: PHP Accept-encoding: identity 
Authorization: Bearer <TOKEN IS HERE> 
GData-Version: 2.0 
X-GData-Key: key=<MYKEYISHERE>
Slug: throwing_can.mp4 
Content-Type: multipart/related; boundary="5170429d1b193" 
Content-Length: 3920610 

Сам файл разбит на части и записан в поток.

function ytapi_write_file($handle, $path, $chunksize = 8192){
    $filehandle = fopen($path, 'r');
    while(!feof($filehandle)){
        fwrite($handle, fread($filehandle, $chunksize));
    }
    fclose($filehandle);
    $filehandle = null;
}

function ytapi_write($handle, $request){
    fwrite($handle, $request);
    return $request;
}

Вот так.

ytapi_write($handle, $start); //This writes the header.
ytapi_write_file($handle, $path, 8192); //This writes the file raw/binary.
ytapi_write($handle, $end); //This writes the final boundary.

Также я использую это для информации заголовка:

$_header = array(
    'Host'=>'gdata.youtube.com',
    'Connection'=>'close',
    'User-Agent'=>'PHP',
    'Accept-encoding'=>'identity'
);

Есть идеи, что я делаю неправильно? При необходимости я могу предоставить дополнительную информацию. Файл, который я загружаю, имеет размер немногим более 3 МБ, файл, который находится на рассматриваемом сервере. Я проверил правильное местоположение.

ОБНОВИТЬ

Изменено на uploads.gdata.youtube.com

Теперь я получаю это сообщение об ошибке:

Host: uploads.gdata.youtube.com
Connection: close
User-Agent: PHP
Accept-encoding: identity
tcp://uploads.gdata.youtube.com:80HTTP/1.1 400 Bad Request
Server: HTTP Upload Server Built on Apr 8 2013 13:06:58 (1365451618)
X-GData-User-Country: US
Content-Type: application/vnd.google.gdata.error+xml
X-GUploader-UploadID: <SOME ID>
Date: Thu, 18 Apr 2013 19:42:14 GMT
Pragma: no-cache
Expires: Fri, 01 Jan 1990 00:00:00 GMT
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 228
Connection: close
1
cngodles 18 Апр 2013 в 23:25
Изменено на uploads.gdata.youtube.com
 – 
cngodles
18 Апр 2013 в 23:43
Думаю, должен быть https
 – 
dikirill
18 Апр 2013 в 23:48
1
Разве вы не можете использовать CURL из моего примера? Вам не нужно иметь дело с Content-Length и фрагментами файлов.
 – 
dikirill
18 Апр 2013 в 23:49
Сейчас пытаюсь реализовать.
 – 
cngodles
18 Апр 2013 в 23:51
Сервер отправляет обратно объект в формате XML. О каком сообщении об ошибке на самом деле говорится в этом XML?
 – 
Remy Lebeau
19 Апр 2013 в 01:56

1 ответ

Лучший ответ

Это была моя реализация:

$data = '<?xml version="1.0"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<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">' . trim($description) . '</media:description>
        <media:keywords>' . $tags . '</media:keywords>
        <media:category scheme="http://gdata.youtube.com/schemas/2007/categories.cat">Music</media:category>
    </media:group>
</entry>';
$headers = array(
    'Authorization: GoogleLogin auth=' . $auth,
    'GData-Version: 2',
    'X-GData-Key: key=<KEY>',
    'Slug: ' . basename($videoPath)
);

$tmpfname = tempnam("/tmp", "youtube");
$handle = fopen($tmpfname, "w");
fwrite($handle, $data);
fclose($handle);

$post = array(
    'xml' => '@' . $tmpfname . ";type=application/atom+xml",
    'video' => '@' . $videoPath . ";type=video/mp4",
);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "uploads.gdata.youtube.com/feeds/api/users/default/uploads");
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$content = curl_exec($ch);
curl_close($ch);
1
dikirill 18 Апр 2013 в 23:38
Что такое переменная $ auth? Подтвержденный токен? Очень рада помощи! :)
 – 
cngodles
18 Апр 2013 в 23:49
1
Да. '<ЖЕТОН ЗДЕСЬ>'. Я беру это из запроса "google.com/accounts/ClientLogin" с "Электронная почта" и " Passwd '. Не работал с OAuth.
 – 
dikirill
18 Апр 2013 в 23:50
Хорошо, запустил свой пример и не получил ошибки. Еще не появилось в моем списке видео на YouTube, поэтому не уверен, сработало это или нет. Надеюсь.
 – 
cngodles
18 Апр 2013 в 23:56
1
Var_dump ($ content) после curl_close ($ ch);
 – 
dikirill
18 Апр 2013 в 23:58
Изменил его на «Авторизация: предъявитель». $ auth. РАБОТАЛ! наконец, после недели боли. Я пришлю вам код oAuth, если хотите, это довольно просто.
 – 
cngodles
19 Апр 2013 в 00:01