2013-04-18 8 views
8

Ich möchte ein Video direkt auf Youtube von meinem Server, für den ich PHP curl bin, hochladen.PHP curl ändert den Inhaltstyp in application/x-www-form-urlencoded. Sollte das nicht tun

Ich brauche diese Anfrage Format:

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-- 

Das ist, was ich habe:

$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 das Ergebnis zeigt mir, dass Locke die Content-Type zu application/x-www-form-urlencoded geändert, was natürlich nicht von youtube unterstützt .

Ich bin meine binäre Inhalte (das Video) in CURLOPT_POSTFIELDS, vielleicht ist das falsch, aber ich weiß nicht, wie Sie den Anfragekörper anders als das einstellen.

Wie behalte ich meinen Inhaltstyp, den ich einstelle?

+1

Gemäß der Dokumentation 'CURLOPT_POST' wird der' Content-Type' automatisch auf 'application/x-www-form-urlencoded' gesetzt. Versuchen Sie vielleicht, diese Option und den 'CURLOPT_HEADER' in einzelnen Anweisungen zu setzen, oder zumindest letzteres in einer einzigen Anweisung mit 'curl_setopt' * nach * der Methode. – Havelock

+1

Arbeitete. Könnten Sie das als Antwort posten, damit ich es akzeptieren kann? –

Antwort

7

Gemäß der documentation section regarding the options' parameter Einstellung der HTTP-Methode auf POST ist standardmäßig der Inhaltstyp auf application/x-www-form-urlencoded festgelegt. Mein Verdacht besteht also darin, dass alle Ihre Optionen gleichzeitig gesetzt werden und Ihre Content-Type überschrieben wird.
Mein Vorschlag wäre, den Inhaltstyp in einer einzigen Anweisung zu setzen, nachdem Sie das Verfahren festgelegt haben, das heißt

$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

Bitte aktualisieren Sie Ihr Beispiel, es ist kein zweidimensionales Array. Es sollte sein: array ("Authorization:". Sprintf ..., "Content-Type:". Sprintf ....) –

+0

@JohnCongdon: richtig, danke! Es ist lustig, niemand hat es in etwas über zwei Jahren bemerkt, drei Upvotes und "akzeptierte Antwort". (Ich bin sicher, Sie meinten "kein assoziatives Array" statt "kein zweidimensionales Array";)) – Havelock

+0

Schande für die PHP cURL. Nicht nur "CURLOPT_POST" überschreibt den "Content-Type", sondern verhindert, dass die anderen HTTP-Header gleichzeitig gesetzt werden. Danke für diese Lösung! – NeverEndingQueue

10

akzeptierte Antwort für mich nicht hilfreich war und ich ein anderes Problem im Code gefunden. Nach dem aktuellen PHP documentation CURLOPT_HTTPHEADER muss wie folgt eingestellt werden:

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

Es muss eine Liste von Strings sein, nicht ein Hash wie array('Content-Type' => 'text/plain'). Hoffe, es wird die Debugging-Zeit von jemandem sparen.

+1

Mit anderen Worten, Sie können kein assoziatives Array an CURLOPT_HTTPHEADER übergeben, nur einfache Arrays. Dieses Thema hat mich stundenlang verrückt gemacht ... – andreszs