I'm attempting to handle SWA responses from a Java SOAP service. In that SWA response is a binary attachment(s) appended to the end of the XML along with some MIME headers. I cannot use WSO2 for dependency requirement limitations.
Any help would be much appreciated!
// Input
------=_Part_42_539586119.1332526191981
Content-Type: text/xml; charset=UTF-8
Content-Transfer-Encoding: binary
Content-Id: <03B4708A9544C182C43E51D9ADA1E456>
<?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> ... TRUNCATED XML SOAP RESPONSE ... </soapenv:Body></soapenv:Envelope>
------=_Part_42_539586119.1332526191981
Content-Type: image/png
Content-Transfer-Encoding: binary
Content-Id: <D637B1257E3E5EEA06AF0E45494F8448>
BINARY DATA GOES HERE
// End of input
// Script to split the response + return StdObj's like the parent class SoapClient + do something with the files
namespace Project;
class SoapClient extends \SoapClient
{
public function __call ($function_name, $arguments)
{
// have the parent do a soap call, catch the lastResponse() if an error
// occurred (eg has an attachment) and parse it out.
try {
$r = parent::__call($function_name, $arguments);
return $r;
} catch (\Exception $e) {
// Assumption: When this is sent, it means that a file is being sent
// because SimpleXML can't process it.
if ($e->getMessage() == "looks like we got no XML document") {
$response = parent::__getLastResponse();
$partString = "/(------=_[a-zA-Z0-9_\\.]+)/";
$outputArr = preg_split($partString, $response);
// $outputAtt[0] -- empty and is the first MIME Part Header
// $outputArr[1] -- Mime Header + XML (The SOAP Response)
// $outputArr[n+1] -- additional files w/ MIME headers
if (array_key_exists(1, $outputArr)) {
// remove the first 5 lines (4 MIME Header lines) + 1 Blank
// line
$data = implode("\n",
array_slice(explode("\n", $outputArr[1]), 5));
/// Simple XML Object ... appears to be an empty SimpleXMLElement though ... >:-(
$xml = simplexml_load_string($data, null, null, "http://schemas.xmlsoap.org/soap/envelope/");
} else {
// OK Maybe this doesn't actually contain the XML... throw
// the original exception.
throw new \SoapFault($e->getMessage(), $e->getCode(),
$e->getPrevious());
}
} else {
throw new \SoapFault($e->getMessage(), $e->getCode(),
$e->getPrevious());
}
}
}
}
Use a MIME parser for this. It's pretty simple from there:
require_once('MimeMailParser.class.php');
class SwADownloadSoapClient extends SoapClient
{
const ATTACHMENT_DIR = '/path/to/saved/attachments/';
public function __doRequest(
$request, $location, $action, $version, $one_way=0
) {
// Issue the SOAP request as SoapClient would normall
$sResult = parent::__doRequest(
$request, $location, $action, $version, $one_way);
// Handle and parse MIME-encoded messages
// @note We're not doing much inspection
// of the XML payload against the attachments ATM
// so not sure how greatly this lives up to the spec
$sResult = $this->_parseMimeMessage($sResult);
$oParser = new MimeMailParser();
$oParser->setText($sResult);
// Save the attachments
$aAttachments = $oParser->getAttachments();
foreach($aAttachments as $oAttachment) {
$sFile = $oAttachment->filename;
if($rFp = fopen(self::ATTACHMENT_DIR . $sFile, 'w')) {
while($sBytes = $attachment->read())
fwrite($rFp, $sBytes);
fclose($rFp);
}
}
}
}
If you want to more properly implement the spec, you'll need to match up the MIME attachments against the SOAP XML.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With