停车场系统数据中间件
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

90 lines
3.0 KiB

<?php
namespace App\Services\Device;
class CommonService
{
public static function parseMultipart($raw): array
{
// 1. 提取边界
if (!preg_match('/^--([^\s]+)/', $raw, $matches)) {
// 若不是 multipart,尝试当作纯 XML
$xml = simplexml_load_string(trim($raw));
return [
'xml' => $xml ? json_decode(json_encode($xml), true) : null,
'images' => []
];
}
$boundary = $matches[1];
// 2. 按边界分割(保留空块)
$blocks = explode("--$boundary", $raw);
$result = ['xml' => null, 'images' => []];
foreach ($blocks as $block) {
$block = trim($block);
if ($block === '' || $block === '--') {
continue; // 跳过空块和结束标记
}
// 3. 分离头部和内容(分隔符:\r\n\r\n 或 \n\n)
$sepPos = strpos($block, "\r\n\r\n");
if ($sepPos === false) {
$sepPos = strpos($block, "\n\n");
}
if ($sepPos === false) {
continue; // 未找到分隔,跳过
}
$headers = substr($block, 0, $sepPos);
$body = substr(
$block,
$sepPos + 4
); // 跳过 \r\n\r\n,如果是 \n\n 这里会多一个字符,但后续 trim 会处理
// 4. 根据头部判断类型
$isXml = strpos($headers, 'filename="mnpr.xml"') !== false
|| strpos($headers, 'text/xml') !== false;
$isImage = strpos($headers, 'image/') !== false
|| preg_match(
'/\.(jpg|jpeg|png|gif|bmp|webp)/i',
$headers
);
if ($isXml) {
// 清理可能残留的尾部边界标记
$xmlString = trim($body);
// 移除尾部可能出现的 -- 或空白
$xmlString = preg_replace('/\s*--\s*$/', '', $xmlString);
// 尝试解析 XML
libxml_use_internal_errors(true);
$xmlObj = simplexml_load_string($xmlString);
if ($xmlObj !== false) {
$result['xml'] = json_decode(json_encode($xmlObj), true);
} else {
// 如果解析失败,将原始字符串保留(可记录错误)
$result['xml'] = $xmlString; // 或 null
}
}
if ($isImage) {
// 提取文件名(可选)
preg_match('/filename="([^"]+)"/', $headers, $fname);
$filename = $fname[1] ?? 'image.jpg';
// 清除可能残留的尾部边界标记(二进制数据不要 trim!)
$imageData = preg_replace('/\s*--\s*$/', '', $body);
$result['images'][] = [
'filename' => $filename,
'data' => $imageData // 原始二进制
];
}
}
return $result;
}
}