This tutorial was created with Delphi 5, but it should work fine with previous versions. You will need the Enterprise (or Client/Server) version of Delphi to create Web Applications.
Delphi Example
Create a new Web Application (File->New->Web Server Application, ISAPI DLL) and add a new Action. Set the PathInfo to '/motorcycle.jpg' and in the OnAction event add the following code:
procedure TWebModMain.WebModMainwbactnGetJpegAction(Sender: TObject;
Request: TWebRequest; Response: TWebResponse; var Handled: Boolean);
// Helper function to get the current directory the DLL is in
function GetDllDir: string;
begin
SetLength(Result, MAX_PATH+1); // Add 1 for the null character
GetModuleFileName(hInstance, PChar(Result), MAX_PATH+1);
SetLength(Result, Length(PChar(Result)));
Result := ExtractFilePath(Result);
end;
var
FileStream: TFileStream;
begin
// This demonstrates returning a Jpeg file from a file on the hard drive.
try
FileStream := TFileStream.Create(GetDllDir + 'motorcycle.jpg', fmOpenRead);
// Note that the file 'motorycle.jpg' must be in the same
// directory as this DLL.
FileStream.Position := 0; // Go to the start of the stream
Response.ContentStream := FileStream;
Response.ContentType := 'image/jpeg';
Response.SendResponse;
// Notice that the stream is not freed (it shouldn't be!)
except // Catch all exceptions and show a custom message
on E: Exception do
Response.Content := '<html><body>An error occurred ' +
E.ClassName + ': ' + E.Message + '</body></html>';
end;
end;
The first thing you will see is the helper function GetDllDir that simply get's the current directory the DLL resides in. You will have to put the file 'motorcycle.jpg' in the same directory as your ISAPI dll for this to work correctly.
Something to notice is how the whole function is wrapped in a try..except so that I can show a custom error message if something goes wrong. The TFileStream.Create can potentially raise an exception if the file passed to it doesn't exist or is locked.
Next, the Response.ContentStream is set to the FileStream we just created. Once you do this note that you should not free the stream. It is taken care of for you in the TWebResponse destructor.
Then the Response.ContentType is set based on what we are sending (a Jpeg in this case), and the Response is sent with Response.SendResponse.
One thing which you may want to do is send other file types. A problem you may encounter is what to set the Response.ContentType to. This can easily be solved in code by looking up the ContentType in the registry:
// MimeType is a string
Reg := TRegistry.Create;
try
Reg.RootKey := HKEY_CLASSES_ROOT;
if Reg.OpenKey(ExtractFileExt(FileName), False) then
begin
if Reg.ValueExists('Content Type') then
MimeType := Reg.ReadString('Content Type');
Reg.CloseKey;
end;
finally
Reg.Free;
end;
Of course, if the ContentType wasn't found, you will probably want to default to something such as 'text/plain' (plain text).
Another thing which you may be interested in doing is setting the "suggested file name" when a user goes to download a file by sending back a response other than an image. This can easily be done by adding a custom Content-Disposition header field:
Response.CustomHeaders.Add('Content-Disposition=; ' +
'filename="Suggested Name.ext"');
If you would like to know more about what you can do with the Content-Disposition header, take a look at the RFC: http://www.w3.org/Protocols/rfc2616/rfc2616-sec19.html
|