getHeaderLine('Content-Type'); if (!preg_match('/multipart\/form-data;\s*boundary=(?:(?:"([^"]+)")|([^;\s]+))/i', $contentType, $m)) { throw new \RuntimeException('Invalid multipart Content-Type'); } $boundary = $m[1] !== '' ? $m[1] : $m[2]; $rawBody = (string)$request->getBody(); if ($rawBody === '') { $rawBody = (string)file_get_contents('php://input'); } $delimiter = "--" . $boundary; $parts = explode($delimiter, $rawBody); $fields = []; $files = []; foreach ($parts as $part) { $part = ltrim($part, "\r\n"); $part = rtrim($part, "\r\n"); if ($part === '' || $part === '--') { continue; } $split = preg_split("/\r\n\r\n/", $part, 2); if (!$split || count($split) !== 2) { continue; } [$rawHeaders, $body] = $split; $headers = self::parseHeaders($rawHeaders); $cd = $headers['content-disposition'] ?? ''; if (!preg_match('/name="([^"]+)"/i', $cd, $nm)) { continue; } $name = $nm[1]; $filename = null; if (preg_match('/filename="([^"]*)"/i', $cd, $fm)) { $filename = $fm[1]; } $body = preg_replace("/\r\n\z/", '', $body); if ($filename !== null && $filename !== '') { $files[$name] = [ 'field' => $name, 'filename' => $filename, 'content_type' => $headers['content-type'] ?? 'application/octet-stream', 'content' => $body, ]; } else { $fields[$name] = $body; } } return ['fields' => $fields, 'files' => $files]; } private static function parseHeaders(string $rawHeaders): array { $headers = []; foreach (preg_split('/\r\n/', $rawHeaders) as $line) { $line = trim($line); if ($line === '' || strpos($line, ':') === false) { continue; } [$k, $v] = explode(':', $line, 2); $headers[strtolower(trim($k))] = trim($v); } return $headers; } }