Reputation: 4128
Using SoapClient directly I get an exception: 'looks like we got no XML document', but by catching the exception, and accessing the $client->__lastReponse()
I get the full message - which is described here: http://www.w3.org/TR/SOAP-attachments#SOAPMultipart
Example:
------=_Part_13_5075710.1359624351743
Content-Type: text/xml; charset=UTF-8
Content-Transfer-Encoding: binary
Content-Id: <740ABC2FC7835A4DF5526C699A3C302D>
<?xml version="1.0" encoding="UTF-8"?><soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><soapenv:Body><ns1:GetOneFileResponse soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:ns1="http://schemas.cisco.com/ast/soap/"><DataHandler href="cid:8D6C4A5AD0F2C0339324FBFC92417B5C" xsi:type="ns2:DataHandler" xmlns:ns2="DimeGetFileService"/></ns1:GetOneFileResponse></soapenv:Body></soapenv:Envelope>
------=_Part_13_5075710.1359624351743
Content-Type: application/octet-stream
Content-Transfer-Encoding: binary
Content-Id: <8D6C4A5AD0F2C0339324FBFC92417B5C>
Binary data here
------=_Part_13_5075710.1359624351743--
What's the proper way of parsing this, assuming that binary data is my example request, as text, that I'm attempting to download through the SOAP service.
I want to solve this without any extra extension such as WSO2 which seems to have Binary attachment ( MTOM ) handling capability, but requires extension
Upvotes: 3
Views: 3981
Reputation: 4128
This most definitely isn't the "proper way" to do this, but it worked for my usecase:
$client = new SoapClient($wsdl);
try {
$client->MySoapFunction($argument);
} catch (SoapFault $e)
{
if ($e->getMessage() == 'looks like we got no XML document') {
$response = $client->__getLastResponse();
$data = $this->_stripSoapHeaders($response);
return $this->_parseMimeData($data);
}
protected function _stripSoapHeaders($response)
{
// Find first occurance of xml tag
preg_match('/(?<xml><.*?\?xml version=.*>)/', $response, $match);
$xml = $match['xml'];
// Strip SOAP http headers, and SOAP XML
$offset = strpos($response, $xml) + strlen($xml . PHP_EOL);
return substr($response, $offset);
}
protected function _parseMimeData($data)
{
// Find MIME boundary string
preg_match('/--(?<MIME_boundary>.+?)\s/', $data, $match);
$mimeBoundary = $match['MIME_boundary']; // Always unique compared to content
// Copy headers to client
if (preg_match('/(Content-Type: .+?)'.PHP_EOL.'/', $data, $match)) {
header($match[1]);
}
$contentType = $match[1];
if (preg_match('/(Content-Transfer-Encoding: .+?)'.PHP_EOL.'/', $data, $match)) {
header($match[1]);
}
// Remove string headers and MIME boundaries from data
preg_match('/(.*Content-Id.+'.PHP_EOL.')/', $data, $match);
$start = strpos($data, $match[1]) + strlen($match[1]);
$end = strpos($data, "--$mimeBoundary--");
$data = substr($data, $start, $end-$start);
return trim($data, "\r\n");
}
Using the above code, I successfully downloaded gzipped binary files through the SOAP API.
Upvotes: 1