2013-04-18 9 views
8

Chcę przesłać wideo bezpośrednio na Youtube z mojego serwera, dla którego używam curl PHP.Skrót PHP zmienia typ zawartości na application/x-www-form-urlencoded. Nie powinienem tego robić

muszę tego formatu żądanie:

POST /feeds/api/users/default/uploads HTTP/1.1 
Host: uploads.gdata.youtube.com 
Authorization: Bearer ACCESS_TOKEN 
GData-Version: 2 
X-GData-Key: key=adf15ee97731bca89da876c...a8dc 
Slug: video-test.mp4 
Content-Type: multipart/related; boundary="f93dcbA3" 
Content-Length: 1941255 
Connection: close 

--f93dcbA3 
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"> 
    <media:group> 
    <media:title type="plain">Bad Wedding Toast</media:title> 
    <media:description type="plain"> 
     I gave a bad toast at my friend's wedding. 
    </media:description> 
    <media:category 
     scheme="http://gdata.youtube.com/schemas/2007/categories.cat">People 
    </media:category> 
    <media:keywords>toast, wedding</media:keywords> 
    </media:group> 
</entry> 
--f93dcbA3 
Content-Type: video/mp4 
Content-Transfer-Encoding: binary 

<Binary File Data> 
--f93dcbA3-- 

To jest to, co mam:

$content = $this->buildRequestContent(); 

$ch = curl_init(); 

$curlConfig = array(
    CURLOPT_URL => 'http://uploads.gdata.youtube.com/feeds/api/users/default/uploads', 
    CURLOPT_POST => true, 
    CURLOPT_RETURNTRANSFER => true, 
    CURLOPT_BINARYTRANSFER => true, 
    CURLOPT_POSTFIELDS => $content, 
    CURLOPT_HTTPHEADER, array(
     "Authorization" => sprintf("GoogleLogin auth=%s", $this->accessToken), 
     "GData-Version" => 2, 
     "X-GData-Key" => sprintf("key=%s", $this->developerKey), 
     "Slug" => sprintf("%s", $this->video->getFilename()), 
     "Content-Type" => sprintf("multipart/related; boundary=\"%s\"", $this->boundaryString), 
     "Content-Length" => strlen($content), 
     "Connection" => "close" 
    ), 
); 

curl_setopt_array($ch, $curlConfig); 

$result = curl_exec($ch); 

Dumping wynik pokazuje mi, że zwijają zmienił Content-Type do application/x-www-form-urlencoded co oczywiście nie jest obsługiwana przez YouTube .

Umieściłem moją zawartość binarną (wideo) w CURLOPT_POSTFIELDS, może to jest złe, ale nie wiem, jak ustawić ciało żądania inne niż to.

Jak zachować określony przeze mnie typ zawartości?

+1

Zgodnie z dokumentacją 'CURLOPT_POST' ustawia" Content-Type "automatycznie na" application/x-www-form-urlencoded ". Spróbuj ustawić tę opcję i 'CURLOPT_HEADER' w pojedynczych instrukcjach lub przynajmniej w drugiej instrukcji za pomocą' curl_setopt' * po * ustawieniu metody. – Havelock

+1

Pracował. Czy możesz to opublikować jako odpowiedź, abym mógł ją zaakceptować? –

Odpowiedz

7

Zgodnie z ustawieniem documentation section regarding the options' parameter domyślną metodą HTTP na POST jest ustawiony typ zawartości na application/x-www-form-urlencoded. Tak więc podejrzewam, że ustawienie wszystkich opcji naraz skutkuje nadpisaniem Twojej Content-Type.
Moja sugestia byłoby ustawić typ zawartości w jednym rachunku, po tym, jak ustawić metodę, tj

$curlConfig = array(
    CURLOPT_URL => 'http://uploads.gdata.youtube.com/feeds/api/users/default/uploads', 
    CURLOPT_POST => true, 
    CURLOPT_RETURNTRANSFER => true, 
    CURLOPT_BINARYTRANSFER => true, 
    CURLOPT_POSTFIELDS => $content, 
); 

curl_setopt_array($ch, $curlConfig); 

curl_setopt($ch, CURLOPT_HTTPHEADER, array(
    'Authorization: ' . sprintf('GoogleLogin auth=%s', $this->accessToken), 
    'GData-Version: 2', 
    'X-GData-Key: ' . sprintf('key=%s', $this->developerKey), 
    'Slug: ' . sprintf('%s', $this->video->getFilename()), 
    'Content-Type: ' . sprintf('multipart/related; boundary="%s"', 
            $this->boundaryString), 
    'Content-Length: ' . strlen($content), 
    'Connection: close' 
)); 
+0

Zaktualizuj swój przykład, nie jest to tablica dwuwymiarowa. Powinien to być: array ("Authorization:". Sprintf ..., "Content-Type:". Sprintf ....) –

+0

@JohnCongdon: poprawne, dzięki! To zabawne, nikt nie zauważył tego w ciągu nieco ponad dwóch lat, trzech awansów i "zaakceptowanej odpowiedzi". (Jestem pewien, że chodziło o "nie tablicę asocjacyjną" zamiast "nie dwuwymiarową tablicę";)) – Havelock

+0

Wstyd dla cURL PHP. Nie tylko 'CURLOPT_POST' nadpisuje' Content-Type', ale zapobiega ustawieniu innych nagłówków HTTP w tym samym czasie. Dzięki za to rozwiązanie! – NeverEndingQueue

10

Akceptowane odpowiedź nie była pomocna dla mnie i znalazłem kolejny problem w kodzie. Według aktualnego PHP documentation CURLOPT_HTTPHEADER muszą być ustawione tak:

curl_setopt($ch, CURLOPT_HTTPHEADER, array(
    'Content-type: text/plain', 
    'Content-length: 100' 
)); 

To musi być lista ciągów, a nie jak array('Content-Type' => 'text/plain') hash. Mam nadzieję, że uratuje czyjś czas debugowania.

+1

Innymi słowy, nie można przekazać tablicy asocjacyjnej do CURLOPT_HTTPHEADER, tylko proste tablice. Ten problem doprowadzał mnie do szaleństwa przez wiele godzin ... – andreszs

Powiązane problemy