In this tutorial, I'll show you how you can use Indy to upload files to a Web Server (either an ISAPI or ASP) that can accept file uploads using the W3C specified multipart/form-data encoding type.
In this tutorial and the project we build here, we'll use the server mentioned in the tutorial above as our test server. It's a good test that shows that the protocol used by the Indy built client application matches that of a regular browser. A kind of confirmation if you will.
To assist us in this task, I've built a simple class derived from a TMemoryStream that encapsulates the nitty-gritty of the multipart/form-data encoding protocol.
The class delaration of the
TMsMultipartFormDataStream class.
TMsMultiPartFormDataStream = class(TMemoryStream)
private
FBoundary: string;
FRequestContentType: string;
function GenerateUniqueBoundary: string;
public
procedure AddFormField(const FieldName, FieldValue: string);
procedure AddFile(const FieldName, FileName, ContentType: string; FileData: TStream); overload;
procedure AddFile(const FieldName, FileName, ContentType: string); overload;
procedure PrepareStreamForDispatch;
constructor Create;
property Boundary: string read FBoundary;
property RequestContentType: string read FRequestContentType;
end;
This class allows for uploading multiple files along with multiple form fields. As you can see, the interface is very simple to understand and use. So I won't go into the details of each of them.

The most important point to remember is that once you've
added the form fields, and files that you need, you
must call the
PrepareStreamForDispatch method
before you send the stream.
Building the Application
This is a simple application that uses the test server found at the URL http://www.matlus.com/scripts/multifileupload.dll/upload. This is essentially the HTML form's action attribute if you were to use a browser or the AURL parameter of the IdHTTP component.
Show the GUI Interface of the Application
The
Send button's
OnClick event looks like this:
procedure TForm1.Button2Click(Sender: TObject);
var
ResponseStream: TMemoryStream;
MultiPartFormDataStream: TMsMultiPartFormDataStream;
begin
MultiPartFormDataStream := TMsMultiPartFormDataStream.Create;
ResponseStream := TMemoryStream.Create;
try
IdHttp1.Request.ContentType := MultiPartFormDataStream.RequestContentType;
MultiPartFormDataStream.AddFormField('PersonName', edtPersonName.Text);
MultiPartFormDataStream.AddFormField('Description', edtDescription.Text);
MultiPartFormDataStream.AddFile(edtFile.Name, edtFile.Text, edtMIMEType.Text);
{ You must make sure you call this method *before* sending the stream }
MultiPartFormDataStream.PrepareStreamForDispatch;
MultiPartFormDataStream.Position := 0;
IdHTTP1.Post(edtHost.Text, MultiPartFormDataStream, ResponseStream);
finally
MultiPartFormDataStream.Free;
ResponseStream.Free;
end;
end;
Testing
The application we build uses the test server mentioned earlier. Once you have used this application to upload a file, you can download the file using your browser using the URL http://www.matlus.com/scripts/multifileupload.dll/upload/filename. Be sure to include the file extension as well. In this way, you can confirm that the file you've just uploaded was uploaded without a hitch. For this code to work in your production environment, you need to be certain that the ISAPI or ASP etc. supports uploading files larger than 48K and the multipart/form-data ENC-TYPE W3c spec.