13 Stimmen

Mischen mehrerer Werte für denselben Schlüssel und Datei-Uploads mit cURL und PHP

Ich bin auf eine Einschränkung in den cURL-Bindings für PHP gestoßen. Es scheint, dass es keine einfache Möglichkeit gibt, mehrere Werte für denselben Schlüssel für Postfields zu senden. Die meisten Workarounds, auf die ich gestoßen bin, bestanden darin, die URL-kodierten Postfelder von Hand zu erstellen (tag=foo&tag=bar&tag=baz), anstatt die assoziative Array-Version von CURLOPT_POSTFIELDS zu verwenden.

Es scheint, wie eine ziemlich gemeinsame Sache zu müssen, um zu unterstützen, so dass ich das Gefühl, ich muss etwas verpasst haben. Ist dies wirklich der einzige Weg, um mehrere Werte für den gleichen Schlüssel zu behandeln?

Während diese Problemumgehung als praktikabel (wenn auch nicht wirklich ärgerlich) angesehen werden könnte, ist mein Hauptproblem, dass ich in der Lage sein muss, mehrere Werte für den gleichen Schlüssel zu tun und auch Datei-Upload unterstützen. Soweit ich sagen kann, Dateiupload mehr oder weniger erfordert, um die assoziierte arravy Version von CURLOPT_POSTFIELDS zu verwenden. Ich fühle mich also wie ich bin stecken.

Ich habe gepostet Ich habe dieses Problem auf der cURL-PHP-Mailingliste ausführlicher beschrieben, in der Hoffnung, dass dort jemand eine Idee dazu hat.

Für Vorschläge oder Hinweise, wo ich weitere Informationen zu diesem Thema finden kann, bin ich sehr dankbar!

1voto

lImbus Punkte 1567

Ich denke, der etablierte Standard für mehrere Werte in einem Schlüssel (oder demselben Schlüssel) ist die Verkettung mit einem Trennzeichen, wie z. B. bei Mehrfachauswahlen von Optionslisten in Formularelementen. Ich glaube, dieses Begrenzungszeichen ist das Tabulatorzeichen ( \t ) oder das Pipe-Symbol ( | ).

Wenn der Schlüsselname mit [] (wie tag[] ), wandelt PHP die Werte automatisch in ein Array um, damit Sie es bequemer haben.

0 Stimmen

Ich weiß, wie man PHP dazu bringt, ein Array mit tag[] zu akzeptieren, aber das ist nicht das Problem. Ich sende an eine Nicht-PHP-Website mit cURL und muss in der Lage sein, mehrere Werte für denselben Schlüssel (tag) zu senden, und ich konnte cURL nicht dazu bringen, das zu tun, egal ob ich "tag" oder "tag[]" als Parameternamen angebe.

1 Stimmen

Mhmm, ich bin mir nicht sicher, ob ich das richtig verstehe. Sie posten sozusagen auf einem anderen Formular (was völlig in Ordnung ist)? Erlaubt das ursprüngliche html-Formular nicht mehrere Einträge in diesem Formular-Element? Wenn nein, wird der empfangende Code dies nicht erwarten. Wenn ja, nehmen Sie Wireshark und schauen Sie sich an, wie es kodiert ist, und spielen Sie es dann ab.

0 Stimmen

Ich weiß, dass sie mehrere Werte für denselben Tag akzeptieren ( tag=a&tag=b ) und nicht das Format tag[]=a&tag[]=b verwenden. Ich habe einen automatischen Google-Code-Uploader entwickelt, und ich glaube, diese Website ist in Python. Ich musste ein benutzerdefiniertes Postfeld erstellen, um eine Multipart/Formulardaten-Postinfo zu erstellen.

1voto

Beau Simensen Punkte 4498

LImbus und paul, vielen Dank für Ihre Beiträge.

Wenn ich die Kontrolle über das Formular hätte, in das ich schreibe, könnte ich wahrscheinlich eine andere Lösung für dieses Problem finden. Ich habe jedoch keine Kontrolle über das Formular. Und ich bin mir fast sicher, dass die Software, die den Beitrag liest, nicht PHP ist und sich nicht an die tag[]-Standards hält.

Selbst wenn es so wäre, scheint cURL die tag[]-Syntax nicht zu befolgen. Im Grunde habe ich versucht, die folgenden und weder funktionierte ...

curl_setopt($ch, CURLOPT_POSTFIELDS, array('file' => '@/pathtofile', 'tag[]' => array('a', 'b', 'c'));

curl_setopt($ch, CURLOPT_POSTFIELDS, array('file' => '@/pathtofile', 'tag' => array('a', 'b', 'c'));

Und noch einmal, ich glaube nicht, dass die Übergabe von tag[] sowieso funktionieren würde, da das Formular, in das ich schreibe, eigentlich nach "tag" und nicht nach "tag[]" sucht.

Ich habe langsam das Gefühl, dass die cURL-PHP-Bindings dafür keine Unterstützung bieten. Das ist für mich sehr überraschend. Es scheint, wie es ziemlich buchstäblich alles andere tun können, aber es ist nicht in der Lage, etwas einfaches wie dieses zu tun?

0voto

centurian Punkte 1152

VERWENDEN SIE NICHT "GUZZLE :

# at your command line start php interactive
user@group:~:php -a
php > $arr=array('var' => array(1,2,3,4)); 
php > echo http_build_query($arr);
var%5B0%5D=1&var%5B1%5D=2&var%5B2%5D=3&var%5B3%5D=4
php > echo urldecode(http_build_query($arr));
var[0]=1&var[1]=2&var[2]=3&var[3]=4

Sie brauchen also http_build_query wobei Sie ein Hash-Array von Schlüsselwerten übergeben; Ihre (Array-)Variable wird als Schlüssel mit dem Wert eines Arrays anstelle eines skalaren Wertes eingegeben wie 'var' => array(1,2,3,4) . Jetzt, http_build_query kann die Postfelder von curl Befehl:

$fields = array('key1' => 'value1', 'var' => array(1,2,3,4));
$curlPost = \http_build_query($fields);
curl_setopt($ch, CURLOPT_POSTFIELDS, $curlPost);

Das sind 3 Codezeilen! Wie viele 1000e von Codezeilen enthält Guzzle? (*)

Bislang habe ich curl zu:

das ist ein Ersatz von Millionen von Zeilen durch einige 100er!

(*): _das Ergebnis von http_build_query kann weiter nach Ihren Bedürfnissen formatiert werden._

0 Stimmen

Es ist erwähnenswert, dass http_build_query wird standardmäßig auf http_build_query($fields, null, ini_get('arg_separator.output'), PHP_QUERY_RFC1738)

0voto

Ich bin auf das gleiche Problem gestoßen, bei dem ich einen Parameter, der ein Array sein muss, von einem PHP-Server an einen anderen Server senden musste, der nicht '[]' zum Mischen von Werten mit dem gleichen Schlüssel zusammen mit einer Datei verwendet. In Laravel 8 konnte ich dieses Ziel erreichen mit Http-Client (der Http-Client verwendet natürlich guzzle). Hier ist ein Beispiel für meinen Code.

Illuminate\Support\Facades\Http::attach('file', $fileContents, 'file-name')
->post('https://destination' , [['name' => 'tag', 'content' => 'foo'], ['name' => 'tag', 'content' => 'bar']])

-1voto

OCDev Punkte 2131

Ich habe diese Antwort online gefunden und möchte sie hier veröffentlichen, bevor sie verschwindet:

http://yeehuichan.wordpress.com/2011/08/07/sending-multiple-values-with-the-same-namekey-in-curl-post/

function curl_setopt_custom_postfields($ch, $postfields, $headers = null) {
    $algos = hash_algos();
    $hashAlgo = null;
    foreach ( array('sha1', 'md5') as $preferred ) {
        if ( in_array($preferred, $algos) ) {
            $hashAlgo = $preferred;
            break;
        }
    }
    if ( $hashAlgo === null ) { list($hashAlgo) = $algos; }
    $boundary =
        '----------------------------' .
        substr(hash($hashAlgo, 'cURL-php-multiple-value-same-key-support' . microtime()), 0, 12);

    $body = array();
    $crlf = "\r\n";
    $fields = array();
    foreach ( $postfields as $key => $value ) {
        if ( is_array($value) ) {
            foreach ( $value as $v ) {
                $fields[] = array($key, $v);
            }
        } else {
            $fields[] = array($key, $value);
        }
    }
    foreach ( $fields as $field ) {
        list($key, $value) = $field;
        if ( strpos($value, '@') === 0 ) {
            preg_match('/^@(.*?)$/', $value, $matches);
            list($dummy, $filename) = $matches;
            $body[] = '--' . $boundary;
            $body[] = 'Content-Disposition: form-data; name="' . $key . '"; filename="' . basename($filename) . '"';
            $body[] = 'Content-Type: application/octet-stream';
            $body[] = '';
            $body[] = file_get_contents($filename);
        } else {
            $body[] = '--' . $boundary;
            $body[] = 'Content-Disposition: form-data; name="' . $key . '"';
            $body[] = '';
            $body[] = $value;
        }
    }
    $body[] = '--' . $boundary . '--';
    $body[] = '';
    $contentType = 'multipart/form-data; boundary=' . $boundary;
    $content = join($crlf, $body);
    $contentLength = strlen($content);

    curl_setopt($ch, CURLOPT_HTTPHEADER, array(
        'Content-Length: ' . $contentLength,
        'Expect: 100-continue',
        'Content-Type: ' . $contentType,
    ));

    curl_setopt($ch, CURLOPT_POSTFIELDS, $content);

}

Und sie zu benutzen:

curl_setopt_custom_postfields($ch, array(
    'file' => '@a.csv',
    'name' => array('James', 'Peter', 'Richard'),
));

0 Stimmen

Siehe die Antwort von @BeauSimensen unten.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X