Site icon Embarcadero RAD Studio, Delphi, & C++Builder Blogs

Showing Download Progress in Delphi SOAP

the future of starts demands massive productivity

Author: deepak S1409

Download the code for this white paper (dlprogress.zip, 12 KB)

Abstract

This paper talks about how you can show a download “progress” bar (like many download utilities do) when using SOAP to transfer data. I’ve used Delphi 7 in this article, and made some code changes to the source code, so this might not work with any other version of Delphi.

Introduction

If you’ve read the paper in http://www.agnisoft.com/white_papers/SOAP2.asp#binaryfile which tells you how you can transfer binary data using SOAP. In Delphi 7, you can also use the TSOAPAttachment class. But what if you need to use a progress bar to display data being transferred?

There’s an event in the THTTPRio.HTTPWebNode, called OnReceivingData. This event gives you a Size and a Total parameter, but they’re always the same…so you can’t use it to determine the actual download status. Or can you?

Digging into Delphi

Looking at the Delphi SOAP Source code, I realized that I could modify the way this event was being called, and sending real data – where Size would mean the amount that’s currently been downloaded, and Total would give you the expected total size of the download.

Looking into SOAPHTTPTrans.pas (located in the SourceSoap folder under your Delphi 7 install), I found that the procedure Receive was calling the OnReceivingData event. I had to make some modifications to the code as follows: (In the Receive procedure)

Note: Please backup this file before makign any changes.

1. Declare variables, TotalSize and TotalRead as DWORD:

[crayon-6768a5f2c1926369147419/]

2. In the code for the Receive procedure, after the line:

[crayon-6768a5f2c192c032344809/]

Add:

[crayon-6768a5f2c192e501462606/]

Essentially, what we’re doing here is to find out the actual length of the response, given in the Content-Length response header.

3. Further down, within the repeat loop, you’ll see the following code:

[crayon-6768a5f2c192f960417269/]

Replace it with:

[crayon-6768a5f2c1930346278809/]

Here, we’re just ensuring that we keep a sum of the downloaded chunks handy (in the TotalRead variable) and we call the event with the total bytes read and the total bytes available.

4. Remember to include $(DELPHI)SourceSOAP in your client project search path, so that these changes will be compiled into your application.

Demo

I’ve created a simple WAD based server which allows you to download files in the same directory as the WAD application with an IDownloader interface. There’s a function in the interface, DownloadFile implemented as follows:

[crayon-6768a5f2c1932575955263/]

The FileToByteArray comes from the CompressHelper utility unit I’d created for my earlier paper, Transferring binary data using SOAP. I’ve also included it in the source code with this article.

What that piece of code does is to look in the folder (where the server application resides) for the existence of a file with the name given in the FileName parameter. If a file is found, its contents are returned in a dynamic array of bytes.

If you’re wondering what GetCurrentDirectory does:

[crayon-6768a5f2c1933929846418/]

The reason I’ve not used the more commonly known Application.ExeName is that you can use this code even in ISAPI dlls (where Application.ExeName isn’t valid)

The Client Application

I’m skipping the part where you create a new application, import this WSDL etc. I’ve created a form with an edit box for the file name, a Download button, and a progress bar indicator and panel. Here’s the code for the download button:

[crayon-6768a5f2c1934720320389/]

A file is requested from the server, and if it does arrive, we save it to a file in the same folder as the client application. (Here Application.ExeName is ok, because this is a client application that will always be an EXE) I’ve used another CompressHelper function to save the response byte array to disk.

But the code to actually populate the progress bar is in an event – THTTPRio.HTTPWebNode.OnReceivingData:

[crayon-6768a5f2c1935439706292/]

The reason I have Application.ProcessMessages; in there is so that you can actually see the user interface change – otherwise the progress bar does not get updated. (But you probably knew that already)

What have we got?


This.

Caveats?

  1. This works only for Delphi SOAP that uses WinInet. If you use INDY, there’s probably a different approach to making it work.
  2. You can’t use this with a client built using the SOAP package. That’s because your source code changes to SOAPHTTPTrans.pas don’t change the package.
  3. I have also included a Download as Attachment to demonstrate that the changes you made work even with TSOAPAttachments. The source code reveals all.

Who’s Deepak Shenoy?

He’s part of the big pointy haired team at Agni. Update: Deepak now works at FLOvate Technologies.

Download the code for this white paper (dlprogress.zip, 12 KB)

Exit mobile version