13

PHP の cURL バインディングの制限に遭遇しました。ポストフィールドの同じキーに対して同じ複数の値を送信する簡単な方法はないようです。これに関して私が遭遇した回避策のほとんどは、CURLOPT_POSTFIELDS の連想配列バージョンを使用する代わりに、tag=foo&tag=bar&tag=baz) によってエンコードされた URL 投稿フィールドを手動で作成することを伴いました。

サポートする必要があるのはかなり一般的なことのように思えるので、何かを逃したに違いないと感じています. これは、同じキーに対して複数の値を処理する唯一の方法ですか?

この回避策は実行可能であると考えられるかもしれませんが (実際に面倒ではないにしても)、私の主な問題は、同じキーに対して複数の値を実行できる必要があり、ファイルのアップロードもサポートする必要があることです。私が知る限り、ファイルのアップロードには多かれ少なかれ CURLOPT_POSTFIELDS の関連配列バージョンを使用する必要があります。だから行き詰った感じです。

この問題については、cURL PHP メーリング リストに詳細を投稿しました。

これに関する詳細情報をどこで探すことができるかについての提案やヒントは大歓迎です!

4

10 に答える 10

12

マルチパート/フォームデータを使用してカスタム CURLOPT_POSTFIELDS 文字列を作成する独自の関数を作成することになりました。なんてつらい。

function curl_setopt_custom_postfields($ch, $postfields, $headers = null) {
    // $postfields is an assoc array.
    // Creates a boundary.
    // Reads each postfields, detects which are @files, and which values are arrays
    // and dumps them into a new array (not an assoc array) so each key can exist
    // multiple times.
    // Sets content-length, content-type and sets CURLOPT_POSTFIELDS with the
    // generated body.
}

この方法を次のように使用できました。

curl_setopt_custom_postfields($ch, array(
    'file' => '@/path/to/file',
    'tag' => array('a', 'b', 'c'),
));

私は CURLOPT_HTTPHEADER スタックについて確信が持てないので、このメソッドがそれを呼び出すので、必要に応じてユーザーが追加のヘッダーを指定できる関数であることを確認しました。

このブログ投稿で完全なコードを入手できます。

于 2009-01-01T05:07:31.690 に答える
3

名前に not を使用すると、tag[]PHPは配列を生成します。tag

tag=foo&tag=bar&tag=baz

あなたが必要

tag[]=foo&tag[]=bar&tag[]=baz

送信用に urlencoded すると、これは次のようになることに注意してください。

tag%5B%5D=foo&tag%5B%5D=bar&tag%5B%5D=baz
于 2008-12-31T11:03:43.610 に答える
2

私は同じ問題に遭遇しました。ですが、この方法で解決できました。

for($cnt = 0; $cnt < count($siteRows); $cnt++)
{
    $curlParams['site_ids['.$cnt.']'] = $siteRows[$cnt]->site_id; 
}

ファイルでも機能します:

for($cnt = 0; $cnt < count($imageRows); $cnt++)
{
    $curlParams['product_images['.$cnt.']'] = '@'.$imageRows[$cnt]->full_path;
}
于 2010-01-10T00:14:48.380 に答える
2

私はそれを使用して動作させました:

curl_setopt($ch, CURLOPT_POSTFIELDS,array('tag[0]'=>'val0','tag[1]'=>'val1'));

そして、$_POST結果は次$_POST['tag'][0] = 'val0'のようになります。$_POST['tag'][1] = 'val1'

于 2009-11-05T21:03:47.323 に答える
1

1つのキー(または同じキー)の複数の値の確立された標準は、フォーム要素のオプションリストの複数の選択など、区切り文字と連結することだと思います。この区切り文字は、タブ文字(\t)またはパイプ記号(|)だと思います。

[]キー名が(のように)で終了している場合tag[]、PHPはユーザーの便宜のために値を自動的に配列に変換します。

于 2008-12-31T11:49:41.147 に答える
1

lImbus と paul、ご意見ありがとうございます。

投稿先のフォームを制御できれば、この問題の別の解決策を見つけることができるでしょう。ただし、フォームを制御することはできません。そして、この投稿を読んでいるソフトウェアが PHP ではなく、tag[] の標準に従っていないことはほぼ間違いありません。

あったとしても、cURL は tag[] 構文にも従わないようです。基本的に、私は次のことを試しましたが、どちらもうまくいきませんでした...

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'));

繰り返しますが、私が投稿しているフォームは実際には「tag[]」ではなく「tag」を探しているため、tag[] を渡すことはとにかくうまくいくとは思いません。

私は、cURL PHP バインディングがこれを実際にサポートしていないことを実感し始めています。それは私にはとても驚くべきことです。文字通り何でもできるように見えますが、このような単純なことはできませんか?

于 2008-12-31T21:36:42.270 に答える
-1

この回答をオンラインで見つけたので、消える前にここに投稿したいと思います。

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

}

そしてそれを使用するには:

curl_setopt_custom_postfields($ch, array(
    'file' => '@a.csv',
    'name' => array('James', 'Peter', 'Richard'),
));
于 2013-10-04T02:45:07.890 に答える