问题描述
我似乎无法找到这个问题的真正答案所以我在这里:
I can't seem to find a real answer to this problem so here I go:
如何在 multipart / form-data 格式?我知道如果格式正确,原始POST会被自动解析,但我所指的数据来自PUT请求,而PHP没有自动解析。数据是多部分的,如下所示:
How do you parse raw HTTP request data in multipart/form-data
format in PHP? I know that raw POST is automatically parsed if formatted correctly, but the data I'm referring to is coming from a PUT request, which is not being parsed automatically by PHP. The data is multipart and looks something like:
------------------------------b2449e94a11c
Content-Disposition: form-data; name="user_id"
3
------------------------------b2449e94a11c
Content-Disposition: form-data; name="post_id"
5
------------------------------b2449e94a11c
Content-Disposition: form-data; name="image"; filename="/tmp/current_file"
Content-Type: application/octet-stream
�����JFIF���������... a bunch of binary data
我用libcurl发送数据(伪代码):
I'm sending the data with libcurl like so (pseudo code):
curl_setopt_array(
CURLOPT_POSTFIELDS => array(
'user_id' => 3,
'post_id' => 5,
'image' => '@/tmp/current_file'),
CURLOPT_CUSTOMREQUEST => 'PUT'
);
如果我删除了CURLOPT_CUSTOMREQUEST位,请求将作为服务器上的POST处理,并且所有内容都会被解析很好。
If I drop the CURLOPT_CUSTOMREQUEST bit, the request is handled as a POST on the server and everything is parsed just fine.
有没有办法手动调用PHP的HTTP数据解析器或其他一些好的方法呢?
是的,我必须发送请求作为PUT:)
Is there a way to manually invoke PHPs HTTP data parser or some other nice way of doing this?And yes, I have to send the request as PUT :)
推荐答案
好的,所以Dave和Everts建议我决定手动解析原始请求数据。在搜索了大约一天后,我没有找到任何其他方法来做到这一点。
Ok, so with Dave and Everts suggestions I decided to parse the raw request data manually. I didn't find any other way to do this after searching around for about a day.
我得到了一些帮助。我没有像在引用的线程中那样篡改原始数据,因为这会破坏正在上传的文件。所以这都是正则表达式。这并没有很好地测试,但似乎适用于我的工作案例。没有进一步的麻烦,并希望有一天这可能会帮助别人:
I got some help from this thread. I didn't have any luck tampering with the raw data like they do in the referenced thread, as that will break the files being uploaded. So it's all regex. This wasnt't tested very well, but seems to be working for my work case. Without further ado and in the hope that this may help someone else someday:
function parse_raw_http_request(array &$a_data)
{
// read incoming data
$input = file_get_contents('php://input');
// grab multipart boundary from content type header
preg_match('/boundary=(.*)$/', $_SERVER['CONTENT_TYPE'], $matches);
$boundary = $matches[1];
// split content by boundary and get rid of last -- element
$a_blocks = preg_split("/-+$boundary/", $input);
array_pop($a_blocks);
// loop data blocks
foreach ($a_blocks as $id => $block)
{
if (empty($block))
continue;
// you'll have to var_dump $block to understand this and maybe replace \n or \r with a visibile char
// parse uploaded files
if (strpos($block, 'application/octet-stream') !== FALSE)
{
// match "name", then everything after "stream" (optional) except for prepending newlines
preg_match("/name=\"([^\"]*)\".*stream[\n|\r]+([^\n\r].*)?$/s", $block, $matches);
}
// parse all other fields
else
{
// match "name" and optional value in between newline sequences
preg_match('/name=\"([^\"]*)\"[\n|\r]+([^\n\r].*)?\r$/s', $block, $matches);
}
$a_data[$matches[1]] = $matches[2];
}
}
按参考使用(为了不复制数据太多):
Usage by reference (in order not to copy around the data too much):
$a_data = array();
parse_raw_http_request($a_data);
var_dump($a_data);
编辑:这个答案在7年后仍然会定期点击。从那以后我从未使用过此代码,并且不知道这些天是否有更好的方法。请查看下面的评论,并了解有许多情况下此代码无效。使用风险由您自己承担。
this answer is still getting regular hits 7 years later. I have never used this code since then and do not know if there is a better way to do it these days. Please view the comments below and know that there are many scenarios where this code will not work. Use at your own risk.
这篇关于使用PHP手动解析原始multipart / form-data数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!