Экранирование символа CURL @ с помощью PHP

Я пишу php-приложение, которое отправляет через curl-данные, чтобы подписаться на список электронной почты iContact. Однако я продолжаю получать неверную ошибку адреса электронной почты. Я думаю, это может быть связано с тем, что я избегаю символа @, поэтому он выглядит как% 40 вместо @. Кроме того, согласно документации php для curl_setopt с CURLOPT_POSTFIELDS:

Полные данные для отправки в HTTP-режиме «POST». Чтобы опубликовать файл, добавьте имя файла с помощью @ и используйте полный путь.

Итак, есть ли все равно, чтобы передать символ @ в качестве пост-данных через curl в php, не запуская сначала через urlencode?

Solutions Collecting From Web of "Экранирование символа CURL @ с помощью PHP"

http_build_query() используйте http_build_query() в вашем массиве данных, прежде чем передать его curl_setopt() , что приведет к отправке формы в виде application/x-www-form-encoded вместо multipart/form-data (и, следовательно, @ не интерпретировать).

Также почему вы действительно волнуете @ в адресе электронной почты? Это имеет значение только в том случае, если @ – первый символ, а не где-то посередине.

После поиска PHP curl manual, я обнаружил, что нет информации, чтобы избежать первого «@», если поле post является строкой вместо файла, если сообщение с кодировкой multipart / form-data.

Способ, которым я работал над этой проблемой, – это префикс пробела в начале текста. Хотя наш бэкэнд-API будет удалять пробелы, чтобы он мог удалить пустой и восстановить исходный текст. Я не знаю, что погода Twitter API будет обрезать пробелы при вводе пользователя.

Если это так, это обходное решение также работает для вас.

Если кто-то нашел способ избежать первого «@» при использовании PHP curl с кодировкой multipart / form-data, сообщите нам об этом.

Я столкнулся с той же проблемой, хотя и с завитом, а не с завихрением PHP.

При использовании опции поля «rot» в поле « -F » ведущий символ @ не будет отправляться в POST, но вместо этого будет инструктировать curl для отправки имени файла, которое сразу же удастся заменить символ как часть POST.

К счастью, curl предлагает еще одну опцию ' --form-string ', которая ведет себя так же, как ' -F ', за исключением того, что опция «form-string» не анализируется.

Например, если вы хотите использовать curl для поля POST1 со значением «@value» и file1 с файлом «testfile.txt», вы можете сделать это следующим образом:

 curl "http://www.url.com" --form-string "field1=@value" -F "file1=@testfile.txt" 

Это истинное решение, которое поддерживает обе строки, содержащие @ и файлы .

Решение для 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 ), )); } ?> 

@ Ответ PatricDaryll верен, но мне нужно было сделать несколько исследований, чтобы понять, где использовать эту функцию http_build_query .

Чтобы уточнить и обобщить, вместо того, чтобы делать:

  curl_setopt($ch, CURLOPT_POSTFIELDS, $array); 

Вы будете использовать:

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

Простой, но сбивающий с толку … завиток достаточно умен, чтобы понять, дали ли вы ему строку или массив.

Чтобы избежать появления знака @ в данных, отличных от файла, вам необходимо сделать следующее. Подготовьте текстовую строку символом NULL

 $postfields = array( 'upload_file' => '@file_to_upload.png', 'upload_text' => sprintf("\0%s", '@text_to_upload') ); $curl = curl_init(); curl_setopt($curl, CURLOPT_URL, 'http://example.com/upload-test'); curl_setopt($curl, CURLOPT_POSTFIELDS, $postfields); curl_exec($curl); curl_close($curl);