|
Handling AttachmentsOne of the most important features Borland added to Delphi 7 is full support for SOAP attachments. Attachments in SOAP allow you to send data other than XML text, such as binary files or images. In Delphi, attachments are managed through streams. You can read or indicate the type of attachment encoding, but the transformation of a raw stream of bytes into and from a given encoding is up to your code. This process isn't too complex, though, if you consider that Indy includes a number of encoding components. As an example of how to use attachments, I've written a program that forwards the binary content of a ClientDataSet (also hosts images) or one of the images alone. The server has the following interface: type ISoapFish = interface(IInvokable) ['{4E4C57BF-4AC9-41C2-BB2A-64BCE470D450}'] function GetCds: TSoapAttachment; stdcall; function GetImage(fishName: string): TSoapAttachment; stdcall; end; The implementation of the GetCds method uses a ClientDataSet that refers to the classic BIOLIFE table, creates a memory stream, copies the data to it, and then attaches the stream to the TSoapAttachment result: function TSoapFish.GetCds: TSoapAttachment; stdcall; var memStr: TMemoryStream; begin Result := TSoapAttachment.Create; memStr := TMemoryStream.Create; WebModule2.cdsFish.SaveToStream(MemStr); // binary Result.SetSourceStream (memStr, soReference); end; On the client side, I prepared a form with a ClientDataSet component connected to a DBGrid and a DBImage. All you have to do is grab the SOAP attachment, save it to a temporarily in-memory stream, and then copy the data from the memory stream to the local ClientDataSet: procedure TForm1.btnGetCdsClick(Sender: TObject); var sAtt: TSoapAttachment; memStr: TMemoryStream; begin nRead := 0; sAtt := (HttpRio1 as ISoapFish).GetCds; try memStr := TMemoryStream.Create; try sAtt.SaveToStream(memStr); memStr.Position := 0; ClientDataSet1.LoadFromStream(MemStr); finally memStr.Free; end; finally DeleteFile (sAtt.CacheFile); sAtt.Free; end; end;
This code produces the same visual effect as a client application loading a local file into a ClientDataSet, as you can see in Figure 23.7. In this SOAP client I used an HTTPRIO component explicitly to be able to monitor the incoming data (which will possibly be very large and slow); for this reason, I set a global nRead variable to zero before invoking the remote method. In the OnReceivingData event of the HTTPRIO object's HTTPWebNode property, you add the data received to the nRead variable. The Read and Total parameters passed to the event refer to the specific block of data sent over a socket, so they are almost useless by themselves to monitor progress: procedure TForm1.HTTPRIO1HTTPWebNode1ReceivingData( Read, Total: Integer); begin Inc (nRead, Read); StatusBar1.SimpleText := IntToStr (nRead); Application.ProcessMessages; end; |
|
Copyright © 2004-2024 "Delphi Sources" by BrokenByte Software. Delphi Programming Guide |
|