2010-06-25 24 views
8

¿Hay alguna manera de agregar un archivo adjunto de jabón a una solicitud utilizando las clases incorporadas de SoapClient de PHP? Parece que no es compatible, pero ¿puedo construir manualmente los límites de mime? Sé que la biblioteca PEAR SOAP los admite, pero para usarlos tengo que volver a escribir toda la biblioteca para usarla.¿Anexos con SoapClient incorporado de php?

+0

He escrito sobre la solución completa [SoapClient con archivos adjuntos] (http://quickshiftin.com/blog/2013/09/soap-client-attachments-php/) – quickshiftin

Respuesta

3

¿Por qué no solo envía archivos usando Data URI scheme en lugar de implementar SoapAttachment? Aquí está un ejemplo:

Client

$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"; 

salida

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

servidor

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; 
} 

cliente 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)); 
    } 
} 
+0

Eso se ve muy dulce, y gracias por el ejemplo, pero si lo recopilo correctamente, solo está usando un [tipo simple Cadena] (http://docs.oracle.com/cd/E14154_01/dev.835/e12868/e01_soap_types.htm#sthref261) para enviar la imagen. Y como también tiene el servidor, sabe cómo analizar y decodificar la imagen. No creo que funcione en los casos en que solo estoy escribiendo el cliente y el servicio espera un archivo adjunto, ¿o estoy equivocado al respecto? – quickshiftin

+0

@quickshiftin creo que deberías probarlo primero ..... Utilicé [esquema de URI de datos] (http://en.wikipedia.org/wiki/Data_URI_scheme) y lo estoy probando, funciona bien – Baba

+0

Interesante, parece que es donde ese ''datos:'. (function_exists ('mime_content_type')? mime_content_type ($ image): $ mime). '; base64,' 'vino algo, me preguntaba sobre eso. Lo echaré un vistazo más profundo. – quickshiftin

2

Sí, se puede construir el componente MIME del mensaje usando algo como imap_mail_compose.

Deberá construir un mensaje multiparte como lo hacen en el primer ejemplo, colocando el XML del parámetro $request, desde un método Oreemplazado, en la primera parte del mensaje MIME.

Luego puede hacer lo que otros han mostrado en el primer ejemplo imap_mail_compose para agregar una o más partes de mensajes con archivos adjuntos. Estos anexos pueden, pero no tienen que estar codificados en base64, sino que también pueden ser binarios. La codificación para cada parte se especifica mediante encabezados específicos de parte.

También necesitará cocinar un conjunto adecuado de encabezados HTTP, por el SwA Document @Baba vinculado anteriormente.

Una vez que todo está dicho y hecho, usted debe tener algo parecido a los ejemplos de ese documento:

MIME-Version: 1.0 
Content-Type: Multipart/Related; boundary=MIME_boundary; type=text/xml; 
     start="<[email protected]>" 
Content-Description: This is the optional message description. 

--MIME_boundary 
Content-Type: text/xml; charset=UTF-8 
Content-Transfer-Encoding: 8bit 
Content-ID: <[email protected]> 

<?xml version='1.0' ?> 
<SOAP-ENV:Envelope 
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"> 
<SOAP-ENV:Body> 
.. 
<theSignedForm href="cid:[email protected]"/> 
.. 
</SOAP-ENV:Body> 
</SOAP-ENV:Envelope> 

--MIME_boundary 
Content-Type: image/tiff 
Content-Transfer-Encoding: binary 
Content-ID: <[email protected]> 

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

Y que puede enviar a través del cable con lo anterior SoapClient::__doRequest método anulado.Cosas que he notado al tratar de poner en práctica yo mismo hasta el momento:

  • Es posible que necesite para crear un href referencia URI de cada nodo SOAP para el accesorio correspondiente, algo así como href="cid:[email protected]" anterior
  • Necesitará extraer el componente límite del contenido MIME devuelto por imap_mail_compose para su uso en un HTTP Content-Type cabecera
  • no olvide el inicio componente de la Content-Type cabecera o bien, debería ser algo como esto:
  • imap_mail_compose parece bastante mínima (pero fruta madura), si resulta insuficiente, considere Mail_Mime lugar

Content-Type: multipart /Relacionado; boundary = MIME_boundary; type = text/xml; start = ""

Por último, no estoy seguro de qué tan uniforme las diferentes implementaciones de SwA están ahí fuera en el Internet ... Baste decir, que no he sido capaz de conseguir una carga a un servicio remoto con una implementación cruda de lo que he descrito anteriormente. Parece que SwA es el paradigma de apego de SOAP típico de elección, sin embargo, por lo que encuentro leyendo en la red.

Cuestiones relacionadas