10

iContact の電子メール リストにサインアップするために curl データを介して送信する php アプリケーションを作成しています。ただし、無効な電子メールアドレスエラーが発生し続けます。これは、@ 記号をエスケープしているため、@ ではなく %40 のように見えることが原因である可能性があると思います。また、CURLOPT_POSTFIELDSを使用したcurl_setoptのphpドキュメントによると:

HTTP「POST」操作で投稿する完全なデータ。ファイルを投稿するには、ファイル名の先頭に @ を付け、フル パスを使用します。

それで、最初にurlencodeを介して実行せずに、@記号をphpのcurlを介して投稿データとして渡す方法はありますか?

4

6 に答える 6

14

http_build_query()に渡す前に最初に data-array で使用します。これにより、代わりにcurl_setopt()としてフォームが送信されます(したがって、@ は解釈されません)。application/x-www-form-encodedmultipart/form-data

また、なぜメールアドレスの @ を本当に気にするのですか? @ が最初の文字であるかどうかだけが問題であり、途中のどこかではありません。

于 2009-03-15T18:33:44.333 に答える
5

PHP curl マニュアルを検索した後、multipart/form-data エンコーディングで投稿する場合、投稿フィールドがファイルではなく文字列の場合、最初の「@」をエスケープする情報がないことがわかりました。

この問題を回避する方法は、テキストの先頭に空白を追加することです。バックエンド API は空白を取り除き、空白を削除して元のテキストを復元できるようにします。Twitter API がユーザー入力の空白を削除するかどうかはわかりません。

その場合、この回避策も有効です。

multipart/form-data エンコーディングで PHP curl を使用する際に、最初の「@」をエスケープする方法を見つけた場合は、お知らせください。

于 2012-02-04T02:28:03.020 に答える
4

PHPカールではなく、カール自体で同じ問題に遭遇しました。

curl のフィールド オプション ' -F' を使用すると、先頭の @ 記号は POST で送信されませんが、その代わりに、記号の直後に続くファイル名を POST の一部として送信するように curl に指示します。

幸いなことに、curl には別のオプション ' --form-string' があり、' ' と同じように動作し-Fますが、'form-string' オプションは解析されません。

例として、curl を使用して field1 を値 "@value" で、file1 をファイル "testfile.txt" で POST する場合は、次のように実行できます。

curl "http://www.url.com" --form-string "field1=@value" -F "file1=@testfile.txt"
于 2011-12-09T02:48:40.520 に答える
4

これは、文字列を含むファイルとファイルの両方をサポートできる真のソリューションです。@

PHP 5.6 以降のソリューション:

  • CURLFileの代わりに使用し@ます。

PHP 5.5 以降のソリューション:

  • 有効にしCURLOPT_SAFE_UPLOADます。
  • CURLFileの代わりに使用し@ます。

PHP 5.3 以降のソリューション:

  • 自分でマルチパート コンテンツの本文を作成します。
  • Content-Type自分でヘッダーを変更します。

次のスニペットが役立ちます:D

<?php

/**
 * For safe multipart POST request for PHP5.3 ~ PHP 5.4.
 * 
 * @param resource $ch cURL resource
 * @param array $assoc "name => value"
 * @param array $files "name => path"
 * @return bool
 */
function curl_custom_postfields($ch, array $assoc = array(), array $files = array()) {
    
    // invalid characters for "name" and "filename"
    static $disallow = array("\0", "\"", "\r", "\n");
    
    // initialize body
    $body = array();
    
    // build normal parameters
    foreach ($assoc as $k => $v) {
        $k = str_replace($disallow, "_", $k);
        $body[] = implode("\r\n", array(
            "Content-Disposition: form-data; name=\"{$k}\"",
            "",
            filter_var($v), 
        ));
    }
    
    // build file parameters
    foreach ($files as $k => $v) {
        switch (true) {
            case false === $v = realpath(filter_var($v)):
            case !is_file($v):
            case !is_readable($v):
                continue; // or return false, throw new InvalidArgumentException
        }
        $data = file_get_contents($v);
        $v = call_user_func("end", explode(DIRECTORY_SEPARATOR, $v));
        list($k, $v) = str_replace($disallow, "_", array($k, $v));
        $body[] = implode("\r\n", array(
            "Content-Disposition: form-data; name=\"{$k}\"; filename=\"{$v}\"",
            "Content-Type: application/octet-stream",
            "",
            $data,
        ));
    }
    
    // generate safe boundary 
    do {
        $boundary = "---------------------" . md5(mt_rand() . microtime());
    } while (preg_grep("/{$boundary}/", $body));
    
    // add boundary for each parameters
    array_walk($body, function (&$part) use ($boundary) {
        $part = "--{$boundary}\r\n{$part}";
    });
    
    // add final boundary
    $body[] = "--{$boundary}--";
    $body[] = "";
    
    // set options
    return curl_setopt_array($ch, array(
        CURLOPT_POST       => true,
        CURLOPT_POSTFIELDS => implode("\r\n", $body),
        CURLOPT_HTTPHEADER => array(
            "Expect: 100-continue",
            "Content-Type: multipart/form-data; boundary={$boundary}", // change Content-Type
        ),
    ));

}

?>
于 2014-06-05T10:49:03.900 に答える
1

@PatricDaryllの答えは正しいですが、このhttp_build_query関数をどこで使用するかを理解するために少し調査する必要がありました。

明確にして要約するには、次のことを行う代わりに:

     curl_setopt($ch, CURLOPT_POSTFIELDS, $array);

以下を使用します。

     curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($array));

シンプルだけど紛らわしい... curl は、文字列を渡したのか配列を渡したのかを理解するほど賢いです。

于 2014-03-20T14:58:01.023 に答える