使用 PHP 手动解析原始多部分/表单数据数据 [英] Manually parse raw multipart/form-data data with PHP

查看:34
本文介绍了使用 PHP 手动解析原始多部分/表单数据数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我似乎找不到这个问题的真正答案,所以我走了:

I can't seem to find a real answer to this problem so here I go:

如何在 PHP 中解析 multipart/form-data 格式的原始 HTTP 请求数据?我知道如果格式正确,原始 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 :)

推荐答案

编辑 - 请先阅读: 这个答案在 7 年后仍然经常点击.从那以后我再也没有使用过这段代码,也不知道这些天是否有更好的方法来做到这一点.请查看下面的评论,并知道此代码在许多情况下不起作用.使用风险自负.

Edit - please read first: 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.

--

好的,根据 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 
 or 
 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[
|
]+([^

].*)?$/s", $block, $matches);
    }
    // parse all other fields
    else
    {
      // match "name" and optional value in between newline sequences
      preg_match('/name="([^"]*)"[
|
]+([^

].*)?
$/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);

这篇关于使用 PHP 手动解析原始多部分/表单数据数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆