如何在SOAP请求PHP中附加文件

时间:2019-05-30 14:25:24

标签: php soap soap-client

我在尝试将文件附加到我的soap请求时遇到问题。

我已经创建了一个可以处理该请求的工作类。但是我不知道在哪里附加文件。

这绝对是通过soapUI实现的原始查询。

Accept-Encoding: gzip,deflate
Content-Type: multipart/related; type="application/xop+xml"; start="<rootpart@soapui.org>"; start-info="text/xml"; boundary="----=_Part_35_1248651398.1559202098551"
SOAPAction: "http://tempuri.org/IFileStreamService/UploadFile"
MIME-Version: 1.0
Content-Length: 128611
Host: f19-fronter.itslbeta.com:4421
Connection: Keep-Alive
User-Agent: Apache-HttpClient/4.1.1 (java 1.5)


------=_Part_35_1248651398.1559202098551
Content-Type: application/xop+xml; charset=UTF-8; type="text/xml"
Content-Transfer-Encoding: 8bit
Content-ID: <rootpart@soapui.org>

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
  <s:Header><wsse:Security s:mustUnderstand="1" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"><wsse:UsernameToken u:Id="UsernameToken-1682A89E6D8EA12AB6155920209854713"><wsse:Username>88b7e536-249a-4b65-a898-7e81db34ba9a</wsse:Username><wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">89f9577b-f693-49c0-840d-29a1338f1bfd</wsse:Password><wsse:Nonce EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">bNLifo+D9TkVgb2bL0flTw==</wsse:Nonce><u:Created>2019-05-30T07:41:38.546Z</u:Created></wsse:UsernameToken></wsse:Security>
    <h:ExtensionId xmlns:h="http://tempuri.org/">5000</h:ExtensionId>
    <h:Name xmlns:h="http://tempuri.org/">Lavrov1.jpg</h:Name>
  </s:Header>
  <s:Body>
    <StreamMessage xmlns="http://tempuri.org/">
            <Content>
                <inc:Include href="cid:Lavrov1.jpg" xmlns:inc="http://www.w3.org/2004/08/xop/include"/>
            </Content>
    </StreamMessage>
  </s:Body>
</s:Envelope>
------=_Part_35_1248651398.1559202098551
Content-Type: image/jpeg; name=Lavrov1.jpg
Content-Transfer-Encoding: binary
Content-ID: <Lavrov1.jpg>
Content-Disposition: attachment; name="Lavrov1.jpg"; filename="Lavrov1.jpg"

����JFIF��C




��C      

����"�� 
��E
   !1AQa"q2B�#R������3b��C   $%r45S���D����3

现在,我需要用PHP复制它。 我让班级设法处理所有工作。

<?php

require dirname(__DIR__) . '/Helpers/XmlHelper.php';


class ApiFileUploader
{
    /** @var string */
    private $wsdl = 'https://f19-fronter.itslbeta.com:4421/FileStreamService.svc?wsdl';

    /** @var string */
    private $securityHeaderNS = 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd';
    /** @var string  */
    private $extraHeaderNS = 'http://tempuri.org';

    /**
     * @var MMLogger
     */
    private $logger;
    /**
     * @var SoapClient
     */
    private $apiClient;
    /**
     * @var MMConfig
     */
    private $config;

    public function __construct(MMConfig $config, MMLogger $logger)
    {
        $this->config = $config;
        $this->logger = $logger;
    }

    public function uploadFile($fileName)
    {
        $this->logger->dbg('Attempt to upload file ' . $fileName, __METHOD__);

        try {
            $this->initApiClient($fileName);

            $Content = new stdClass();
            $xml = sprintf('<inc:Include href="cid:%s" xmlns:inc="http://www.w3.org/2004/08/xop/include"/>', $fileName);
            $Content->content = new SoapVar($xml, XSD_ANYXML);

            $request = new stdClass();
            $request->Content = new SoapVar($Content, SOAP_ENC_OBJECT);

            $attachment = new ImageObj(__DIR__ . '/../../files/'.$fileName);
            $param = new SoapVar($attachment, SOAP_ENC_OBJECT, "attachment");
            $param = new SoapParam($param, "param");

            /** @noinspection PhpUndefinedMethodInspection */
            $this->apiClient->UploadFile($request);

        } catch (\Throwable $e) {
            $this->logger->error($e->getMessage(), __METHOD__);
        }
        $this->logger->dbgXml(XmlHelper::formatXml($this->apiClient->__getLastRequest()), __METHOD__);
        $this->logger->dbgXml($this->apiClient->__getLastResponse(), __METHOD__);
    }


    private function initApiClient($fileName)
    {
        $this->logger->dbg('Init API client', __METHOD__);
        $this->apiClient = new SoapClient($this->wsdl, array('trace'=>1, 'stream_context' =>
            stream_context_create(array('http'=>array(
                'header'=> 'Accept-Encoding: gzip,deflate'.
                    'SOAPAction: http://tempuri.org/IFileStreamService/UploadFile'.
                    'Content-Type: image/jpeg; name=Lavrov1.jpg'.
                    'Content-Transfer-Encoding: binary'.
                    'Content-ID: <Lavrov1.jpg>'.
                    'Content-Disposition: attachment; name="Lavrov1.jpg"; filename="Lavrov1.jpg'.
                    'MIME-Version: 1.0'.
                    'Content-Length: 128611'
            )))));
        $this->initHeaders($fileName);
    }

    /**
     * Build and load valid SOAP header
     *
     * @param MMConfig $config
     * @return bool
     */
    private function initHeaders($fileName)
    {
        $userName = new SoapVar(
            $this->config->getApiUserName(),
            XSD_STRING,
            null,
            null,
            'Username',
            $this->securityHeaderNS
        );

        $password = new SoapVar(
            $this->config->getApiPassword(),
            XSD_STRING,
            null,
            null,
            'Password',
            $this->securityHeaderNS
        );

        $token = new SoapVar(
            array($userName, $password),
            SOAP_ENC_OBJECT,
            null,
            null,
            'UsernameToken',
            $this->securityHeaderNS
        );

        $securityHeader = new SoapHeader(
            $this->securityHeaderNS,
            'Security',
            new SoapVar(array($token), SOAP_ENC_OBJECT),
            '1'
        );

        $extensionHeader = new SoapHeader(
            $this->extraHeaderNS,
            'ExtensionId',
            new SoapVar(5000, XSD_INT)
        );

        $nameHeader = new SoapHeader(
            $this->extraHeaderNS,
            'Name',
            new SoapVar($fileName, XSD_STRING)
        );

        return $this->apiClient->__setSoapHeaders(array(
            $securityHeader,
            $extensionHeader,
            $nameHeader
        ));
    }
}

class ImageObj{
    function __construct($file, $mime = "") {
        $this->file = $file;
        $this->name = basename($file);
        if (function_exists('mime_content_type')) {
            $this->mime = mime_content_type($file);
        } elseif (function_exists('finfo_open')) {
            $this->mime = finfo_file(finfo_open(FILEINFO_MIME_TYPE), $file);
        } else {
            $this->mime = $mime;
        }

        $this->encoding = "base64";
        $this->data = base64_encode(file_get_contents($file));
    }
}

我从__getLastRequest获得的输出是:

[DBG] ApiFileUploader::uploadFile Attempt to upload file Lavrov1.jpg
[DBG] ApiFileUploader::initApiClient Init API client
[ERR] ApiFileUploader::uploadFile Bad Request
[DBG]  
========== <?xml version="1.0" encoding="UTF-8"?>
  <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://tempuri.org/" xmlns:ns2="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:ns3="http://tempuri.org">
   <SOAP-ENV:Header>
    <ns2:Security SOAP-ENV:mustUnderstand="1">
     <ns2:UsernameToken>
      <ns2:Username>88b7e536-249a-4b65-a898-7e81db34ba9a</ns2:Username>
       <ns2:Password>89f9577b-f693-49c0-840d-29a1338f1bfd</ns2:Password>
      </ns2:UsernameToken>
     </ns2:Security>
      <ns3:ExtensionId>5000</ns3:ExtensionId>
       <ns3:Name>Lavrov1.jpg</ns3:Name>
      </SOAP-ENV:Header>
       <SOAP-ENV:Body>
        <ns1:StreamMessage>
         <ns1:Content>
          <inc:Include href="cid:Lavrov1.jpg" xmlns:inc="http://www.w3.org/2004/08/xop/include"/>
         </ns1:Content>
        </ns1:StreamMessage>
       </SOAP-ENV:Body>
      </SOAP-ENV:Envelope> =========
ApiFileUploader::uploadFile

[DBG]  
==========  =========
ApiFileUploader::uploadFile

主要问题是:如何正确解析标头? (我知道我解析错了。) 该base64编码文件放在哪里? (以我的情况为例)

soapUI的预期响应是:

HTTP/1.1 200 OK
Cache-Control: private
Transfer-Encoding: chunked
Content-Type: multipart/related; type="application/xop+xml";start="<http://tempuri.org/0>";boundary="uuid:360a3acb-26b4-4bdb-9b74-6fc679cec3da+id=2";start-info="text/xml"
Server: Microsoft-IIS/8.5
MIME-Version: 1.0
X-AspNet-Version: 4.0.30319
X-ITSL: ITSL641
X-Powered-By: ASP.NET
Date: Thu, 30 May 2019 07:41:41 GMT


--uuid:360a3acb-26b4-4bdb-9b74-6fc679cec3da+id=2
Content-ID: <http://tempuri.org/0>
Content-Transfer-Encoding: 8bit
Content-Type: application/xop+xml;charset=utf-8;type="text/xml"

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
   <s:Header>
      <o:Security s:mustUnderstand="1" xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
         <u:Timestamp u:Id="_0">
            <u:Created>2019-05-30T07:41:41.484Z</u:Created>
            <u:Expires>2019-05-30T07:46:41.484Z</u:Expires>
         </u:Timestamp>
      </o:Security>
   </s:Header>
   <s:Body>
      <FileStreamUploadResponse xmlns="http://tempuri.org/">
         <FileId>17a13410-9010-4dd4-b396-c21b53be278d</FileId>
      </FileStreamUploadResponse>
   </s:Body>
</s:Envelope>
--uuid:360a3acb-26b4-4bdb-9b74-6fc679cec3da+id=2--

0 个答案:

没有答案