Re: Trying to get SOAP_Attachment to Delphi
| From: | Bart Verkoeijen | Date: | Sat, 10 Apr 2004 14:14:37 +0000 |
| Subject: | Re: Trying to get SOAP_Attachment to Delphi | ||
| References: | 1 | Groups: | php.soap |
| Request: | Send a blank email to php-soap+get-1485@lists.php.net to get a copy of this message | ||
Hi Blake,
I ran into the same problem. I've tried to transfer binary data with Soap
Attachments, but it simply wouldn't work. Also the documentation on
receiving attachments (for a soap server) is quite small: nothing!
Then I found this page: http://www.agnisoft.com/white_papers/SOAP2.asp
Maybe the same method would work with PEAR::SOAP <=> Delphi, and it did!
First I tried to transfer it with base64Binary types, but this woudn't work.
I received the data from the service, but Delphi could not understand it and
returned a 0 byte file.
Then I tried to pass it as a string (since PHP coded the file as a base64
string...), and it works!
Below you can see the sourcecode of the PEAR::SOAP server and the Delphi
client app. It is not complete - for testing purposes only - but the
download method works... With this example you should be able to create your
own binary transfer SOAP service with PHP and Delphi.
===[PHP Sourcecode]===
<?php
/**
* Test SOAP Server
*/
ini_set( 'include_path', '.;D:\httpdocs\codebase\PEAR' );
class TestSoapServer {
var $__dispatch_map = array(
'downloadFile' => array(
'in' => array( 'filename' => 'string' ),
'out' => array( 'base64file' => 'string' )
),
'uploadFile' => array(
'in' => array( 'filename' => 'string',
'base64file' => 'string' ),
'out' => array( 'successful' => 'boolean' )
)
);
function downloadFile( $filename ){
return base64_encode( file_get_contents('test.jpg') );
}
function uploadFile( $filename, $file ){
return false;
}
}
require_once('SOAP/Server.php');
$server =& new SOAP_Server();
//$server->_auto_translation = true;
$soapclass =& new TestSoapServer();
$server->addObjectMap($soapclass,'urn:TestSoapServer');
if( isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] ==
'POST') {
$server->service( $HTTP_RAW_POST_DATA );
}else{
require_once( 'SOAP/Disco.php' );
header( "Content-type: text/xml" );
$disco = new SOAP_DISCO_Server( $server, 'TestSoapServer' );
echo $disco->getWSDL();
exit;
}
?>
===[PHP Sourcecode]===
As you can see, I've hardcoded the server class methods, so you have to
change those...
===[Delphi(7) Sourcecode]===
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, InvokeRegistry, StdCtrls, ExtCtrls, Rio, SOAPHTTPClient, Types,
IdBaseComponent, IdCoder, IdCoder3to4, IdCoderMIME;
type
TForm1 = class(TForm)
Button1: TButton;
SoapServ: THTTPRIO;
Label1: TLabel;
Base64d: TIdDecoderMIME;
procedure Button1Click(Sender: TObject);
procedure SoapServHTTPWebNode1ReceivingData(Read, Total: Integer);
private
{ Private declarations }
Amount: integer;
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
uses
transfer;
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
var
Mem: TMemoryStream;
begin
Amount := 0;
Mem := TMemoryStream.Create;
try
Base64d.DecodeToStream( WideCharToString(PWideChar((SoapServ as
TestSoapServerPort).downloadFile('bla'))), Mem);
Mem.SaveToFile('test2.jpg');
finally
Mem.Free;
end;
end;
procedure TForm1.SoapServHTTPWebNode1ReceivingData(Read, Total: Integer);
begin
Inc(Amount, Read);
Label1.Caption := IntToStr(Amount);
Application.ProcessMessages;
end;
end.
===[Delphi(7) Sourcecode]===
The base64d object is a base64decode component from Indy. The form contains
a simple download button, a text label (shows the bytes transfered) and the
base64decode component. 'tranfer' is the service interface created by the
WSDL wizard in Delphi.
Keep in mind I am a beginner with Delphi programming, so my code could
contain bugs...
I've transfered succesful two JPEG images, one about 1.1MB.
Hope this helps ;).
Bart Verkoeijen
www.oikoyama.net
"Raltgaither@Yahoo.Com" <raltgaither@yahoo.com> schreef in bericht
news:20040213220232.94648.qmail@pb1.pair.com...
> Hi, All.
>
> I've read the messages here about sending Attachments to Delphi, and
> I've made Dave's "adjustments" to the appropriate files, but I still
> can't get this thing to work.
>
> In Delphi I'm looking for the return value to be "TSoapAttachment". It
> seems to want to be a "TByteDynArray". Here's my server code to generate
> the wsdl:
>
> $this->__dispatch_map['getXML'] = array(
> 'in'=>array(),
> 'out'=>array('response' => 'base64Binary')
> );
>
> If I change 'base64Binary' to 'TSoapAttachment' (cheating, I know),
> Delphi presents the correct return value but I get an error when I click
> the button to load the file.
>
> Here's my actual method:
>
> function getXML(){
> $cm_path = "/home/httpd/httpdocs/services/";
> $cm_file = "test.xml";
>
> if (file_exists($cm_path.$cm_file)){
> return new
> SOAP_Attachment('Response','application/binary',$cm_path.$cm_file);
> }
> else {
> return new SOAP_Value('return', 'application/binary', false);
> }
> }
>
>
> Which part am I screwing up? If it helps, here's my client side in Delphi:
>
> procedure TForm1.Button1Click(Sender: TObject);
> var
> Intrf : CV3_Web_ServicePort;
> xmlDoc : TXMLDocument;
> myStream : TStream;
> myAttachment : TSOAPAttachment;
>
> begin
> Intrf := GetCV3_Web_ServicePort(False, '');
> try
> myAttachment := Intrf.getXML;
> except
> on E : Exception do
> ShowMessage(E.Message);
> end;
> myStream := myAttachment.SourceStream;
> xmlDoc := TXMLDocument.Create(nil);
> xmlDoc.LoadFromStream(myStream);
> ListBox1.Items.AddStrings(xmlDoc.XML);
> end;
>
>
> Any help is much, much appreciated!
>
> Thanks,
> Blake <raltgaither@yahoo.com>