Вложения со встроенным в PHP SoapClient? - PullRequest
8 голосов
/ 25 июня 2010

Есть ли способ добавить мыльное вложение в запрос, используя встроенные в PHP классы SoapClient? Не похоже, что это поддерживается, но, может быть, я могу вручную построить границы MIME? Я знаю, что библиотека PEAR SOAP поддерживает их, но чтобы использовать это, мне нужно переписать всю мою библиотеку, чтобы использовать ее.

Ответы [ 2 ]

5 голосов
/ 31 мая 2013

Почему бы вам просто не отправить файлы, используя схему URI данных , а не внедрить SoapAttachment ?Вот пример:

Клиент

$client = new SoapClient(null, array(
        'location' => "http://localhost/lab/stackoverflow/a.php?h=none",
        'uri' => "http://localhost/",
        'trace' => 1
));

// Method 1 Array
// File to upload
$file = "golf3.png";

// First Example
$data = array();
$data['name'] = $file;
$data['data'] = getDataURI($file, "image/png");
echo "Example 1: ";
echo ($return = $client->upload($data)) ? "File Uploaded : $return bytes" : "Error Uploading Files";

// Method 2 Objects
// File to upload
$file = "original.png";

// Second Example
$attachment = new ImageObj($file);
$param = new SoapVar($attachment, SOAP_ENC_OBJECT, "ImageObj");
$param = new SoapParam($param, "param");
echo "Example 2: ";
echo ($return = $client->uploadObj($attachment)) ? "File Uploaded : $return bytes" : "Error Uploading Files";

Выход

Example 1: File Uploaded : 976182 bytes
Example 2: File Uploaded : 233821 bytes

Сервер

class UploadService {

    public function upload($args) {
        $file = __DIR__ . "/test/" . $args['name'];
        return file_put_contents($file, file_get_contents($args['data']));
    }

    public function uploadObj($args) {
        $file = __DIR__ . "/test/" . $args->name;
        $data = sprintf("data://%s;%s,%s", $args->mime, $args->encoding, $args->data);
        return file_put_contents($file, file_get_contents($data));
    }
}

try {
    $server = new SOAPServer(NULL, array(
            'uri' => 'http://localhost/'
    ));
    $server->setClass('UploadService');
    $server->handle();

} catch (SOAPFault $f) {
    print $f->faultstring;
}

Client Util

// Function Used
function getDataURI($image, $mime = '') {
    return 'data: ' . (function_exists('mime_content_type') ? 
            mime_content_type($image) : $mime) . ';base64,' . 
            base64_encode(file_get_contents($image));
}


// Simple Image Object
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));
    }
}
2 голосов
/ 07 июня 2013

Да, вы можете создать MIME-компонент сообщения, используя что-то вроде imap_mail_compose .

Вам нужно будет создать составное сообщение, как в первом примере, поместив XML из параметра $request из переопределенного метода SoapClient::__doRequest в первую часть сообщения MIME.

Затем вы можете сделать, как другие показали в первом примере imap_mail_compose, чтобы добавить одну или несколько частей сообщений с вложениями. Эти вложения могут, но не обязательно должны быть закодированы в base64, они также могут быть двоичными. Кодировка для каждой части указывается в заголовках для конкретной детали.

Вам также потребуется подготовить соответствующий набор заголовков HTTP в соответствии с Документом SwA @Baba, на который ссылались ранее.

Как только все будет сказано и сделано, у вас должно получиться что-то похожее на примеры из этого документа:

MIME-Version: 1.0
Content-Type: Multipart/Related; boundary=MIME_boundary; type=text/xml;
        start="<claim061400a.xml@claiming-it.com>"
Content-Description: This is the optional message description.

--MIME_boundary
Content-Type: text/xml; charset=UTF-8
Content-Transfer-Encoding: 8bit
Content-ID: <claim061400a.xml@claiming-it.com>

<?xml version='1.0' ?>
<SOAP-ENV:Envelope
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Body>
..
<theSignedForm href="cid:claim061400a.tiff@claiming-it.com"/>
..
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

--MIME_boundary
Content-Type: image/tiff
Content-Transfer-Encoding: binary
Content-ID: <claim061400a.tiff@claiming-it.com>

...binary TIFF image...
--MIME_boundary--

И вы можете отправить это по проводам с помощью вышеупомянутого переопределенного метода SoapClient::__doRequest. До сих пор я заметил, что сам пытался реализовать это:

  • Возможно, вам потребуется создать href URI-ссылку от каждого узла SOAP к соответствующему вложению, что-то вроде href="cid:claim061400a.tiff@claiming-it.com" выше
  • Вам потребуется извлечь компонент border из содержимого MIME, возвращенного imap_mail_compose для использования в HTTP Content-Type header
  • Не забудьте также о компоненте start заголовка Content-Type , он должен выглядеть примерно так:
  • imap_mail_compose выглядит довольно минимально (но низко висящий фрукт), если этого окажется недостаточно, рассмотрите Mail_Mime вместо

Content-Type: Multipart / Related; граница = MIME_boundary; тип = текст / XML; начать = ""

Наконец, я не уверен, насколько равномерно различные реализации SwA есть в Интернете ... Достаточно сказать, что я не смог загрузить на удаленный компьютер сервис с грубой реализацией того, что я описал выше. Похоже, что SwA является типичной парадигмой вложения SOAP, хотя, судя по тому, что я собираю, читая в сети.

...