userland multipart/form-data handler
It's late and I can't test this at the moment but the following should do what you want:
//$boundary = null;
if (is_resource($input = fopen('php://input', 'rb')) === true)
{
while ((feof($input) !== true) && (($line = fgets($input)) !== false))
{
if (isset($boundary) === true)
{
$content = null;
while ((feof($input) !== true) && (($line = fgets($input)) !== false))
{
$line = trim($line);
if (strlen($line) > 0)
{
$content .= $line . ' ';
}
else if (empty($line) === true)
{
if (stripos($content, 'name=') !== false)
{
$name = trim(stripcslashes(preg_replace('~.*name="?(.+)"?.*~i', '$1', $content)));
if (stripos($content, 'Content-Type:') !== false)
{
$tmpname = tempnam(sys_get_temp_dir(), '');
if (is_resource($temp = fopen($tmpname, 'wb')) === true)
{
while ((feof($input) !== true) && (($line = fgets($input)) !== false) && (strpos($line, $boundary) !== 0))
{
fwrite($temp, preg_replace('~(?:\r\n|\n)$~', '', $line));
}
fclose($temp);
}
$FILES[$name] = array
(
'name' => trim(stripcslashes(preg_replace('~.*filename="?(.+)"?.*~i', '$1', $content))),
'type' => trim(preg_replace('~.*Content-Type: ([^\s]*).*~i', '$1', $content)),
'size' => sprintf('%u', filesize($tmpname)),
'tmp_name' => $tmpname,
'error' => UPLOAD_ERR_OK,
);
}
else
{
$result = null;
while ((feof($input) !== true) && (($line = fgets($input)) !== false) && (strpos($line, $boundary) !== 0))
{
$result .= preg_replace('~(?:\r\n|\n)$~', '', $line);
}
if (array_key_exists($name, $POST) === true)
{
if (is_array($POST[$name]) === true)
{
$POST[$name][] = $result;
}
else
{
$POST[$name] = array($POST[$name], $result);
}
}
else
{
$POST[$name] = $result;
}
}
}
if (strpos($line, $boundary) === 0)
{
//break;
}
}
}
}
else if ((is_null($boundary) === true) && (strpos($line, 'boundary=') !== false))
{
$boundary = "--" . trim(preg_replace('~.*boundary="?(.+)"?.*~i', '$1', $line));
}
}
fclose($input);
}
echo '<pre>';
print_r($POST);
echo '</pre>';
echo '<hr />';
echo '<pre>';
print_r($FILES);
echo '</pre>';
Get raw post data
Direct answer: you can not do that. PHP insists on parsing it itself, whenever it sees the multipart/form-data Content-Type. The raw data will not be available to you. Sadly. But you can hack around it.
I hit a similar problem, a partner was sending incorrectly formatted data as multipart/form-data, PHP could not parse it and was not giving it out so I could parse it myself.
The solution? I added this to my apache conf:
<Location "/backend/XXX.php">
SetEnvIf Content-Type ^(multipart/form-data)(.*) NEW_CONTENT_TYPE=multipart/form-data-alternate$2 OLD_CONTENT_TYPE=$1$2
RequestHeader set Content-Type %{NEW_CONTENT_TYPE}e env=NEW_CONTENT_TYPE
</Location>
This will change the Content-Type of incoming request to XXX.php from multipart/form-data to multipart/form-data-alternate, which is enough to block PHP from trying to parse it
After this you can finally read the whole raw data from php://input and parse it yourself.
It is ugly, but I have not found a better or in fact any other solution - short of asking the partner to fix their side.
NB! When you do what I described here, $_FILES will be empty.
Posting an empty filefield with CURLOPT_POSTFIELDS to multipart form
Without refactoring your backend or emulating a multi-part form submission manually I'm pretty sure you won't be able to solve your problem with any CURLOPT_POSTFIELDS
logic alone, also see:
http_request_body_encode
- Generating multipart boundary
- userland multipart/form-data handler
If you insist on trying to solve this using CURL alone, I suggest you inspect the ext/curl source code.
How to handle images sent by a mobile device?
Doesn't appear it's being sent via a form, i.e., <form enctype=multipart/form-data">
and <input type="file">
, so the $_FILES
array won't be populated.
You'll probably need to read:
$HTTP_RAW_POST_DATA
or do:
$rawPost = file_get_contents("php://input");
From the manual:
php://input allows you to read raw
data from the request body. In case of
POST requests, it preferrable to
$HTTP_RAW_POST_DATA as it does not
depend on special php.ini directives.
Moreover, for those cases where
$HTTP_RAW_POST_DATA is not populated
by default, it is a potentially less
memory intensive alternative to
activating
always_populate_raw_post_data.
php://input is not available with
enctype="multipart/form-data".
For more info, check out:
http://php.net/manual/en/wrappers.php.php
http://php.net/manual/en/reserved.variables.httprawpostdata.php
php://input is empty on POST request
Before PHP 5.4 $HTTP_RAW_POST_DATA
is not available with enctype="multipart/form-data"
(with the exception of some SAPI implementations), explanations here:
- http://www.php.net/manual/en/wrappers.php.php
- http://www.php.net/manual/en/ini.core.php#ini.always-populate-raw-post-data
I suggest you give a look to a couple of answers to existing questions:
- php http request content raw data enctype=multipart/form-data
- userland multipart/form-data handler
From PHP 5.4+ you can use the php.ini
directive enable_post_data_reading
to disable PHP consuming the raw data (hence process it), be aware that $_POST
and $_FILES
won't be populated though (refer to Vitaly Chirkov answer).
Empty $_POST without Content-type
You can override/inject the necessary header using Apache mod_headers
if you have to. Or otherwise resort to manually reconstructing the $_POST array. (See also userland multipart/form-data handler)
If it's always urlencoded, simply read from php://input
(Which contains the raw POST request body) and use parse_str
:
parse_str(file_get_contents("php://input"), $_POST);
That should recreate the POST array, pretty much like PHP would do.
Related Topics
Simplexml_Load_String() Fail to Parse Error
How to Escape String from PHP for JavaScript
What Is Difference of Developing a Website in MVC and 3-Tier or N-Tier Architecture
How to Use PHP In_Array with Associative Array
PHP & Hash/Fragment Portion of Url
Phpexcel Download Using Ajax Call
HTML Form PHP Post to Self to Validate or Submit to New Page
Aescrypt Decryption Between iOS and PHP
Get Key of Multidimensional Array
File_Exists() Returns False, But the File Does Exist
Change Cart Total Price in Woocommerce
Create Nested List from Multidimensional Array
But These Conflict with Your Requirements or Minimum-Stability