Ich habe rasch dies mit deinem Code getestet. Delphi 11.2. Win 11 Pro, aktueller IIS. Als CGI in IIS.
Delphi-Quellcode:
program filedownloadcgi;
{$APPTYPE CONSOLE}
uses
WebBroker,
CGIApp,
WebModuleUnit1 in 'WebModuleUnit1.pas' {WebModule1: TWebModule};
{$R *.res}
begin
Application.Initialize;
Application.WebModuleClass := WebModuleClass;
Application.Run;
end.
Delphi-Quellcode:
unit WebModuleUnit1;
interface
uses
System.SysUtils, System.Classes, HTTPApp;
type
TWebModule1 =
class(TWebModule)
procedure WebModuleBeforeDispatch(Sender: TObject; Request: TWebRequest;
Response: TWebResponse;
var Handled: Boolean);
private
{ Private-Deklarationen }
public
{ Public-Deklarationen }
end;
var
WebModuleClass: TComponentClass = TWebModule1;
implementation
{$R *.dfm}
procedure TWebModule1.WebModuleBeforeDispatch(Sender: TObject;
Request: TWebRequest; Response: TWebResponse;
var Handled: Boolean);
var
fn :
string;
begin
fn := paramstr(1) + '
test.bin';
Response.Content := '
';
Response.ContentType := '
application/octet-stream';
Response.ContentStream := TBytesStream.Create;
TBytesStream(Response.ContentStream).LoadFromFile(fn);
Handled := true;
end;
end.
Funktioniert bei mir auch mit 300MB Files ohne Probleme.
Ist nicht 100%ig das, was du machst - aber Webbroker funktioniert also.
Falls du immer noch glaubst, dass es am Speicher liegt, dann prüf doch mal, ob der Tipp mit Response.Location :=... funktioniert. Dann regelt IIS für dich die Übertragung der Files. Daran denken: In IIS die MIME Typen setzen.
Der von dir erwähnte WSock Error 10054 sollte doch als Windows Ereignis geloggt werden? Findest du dort keine Infos?
Und halt doch noch einmal wegen Speicher... Wenn ich mit perfmon beobachte, was passiert, wenn ich deinen LoadFromFile Ansatz verwende, dann sind nach dem LoadFromFile die 300MB Dateidaten zusätzlich im Arbeitsspeicher (erwartet).
Falls ich perfmon vertrauen kann, dann ist es mit TfileStream (erwartet) nicht so. Ich hab's nun auch überprüft: Setze in Web.HttpApp bei procedure TWebResponse.SendStream(AStream: TStream); einen Breakpoint, dann siehst du wie Buffer für Buffer (1MB) gesendet wird und so der Arbeitsspeicher vom Server nicht überlastet wird.
Also so:
Delphi-Quellcode:
procedure TWebModule1.WebModuleBeforeDispatch(Sender: TObject;
Request: TWebRequest; Response: TWebResponse; var Handled: Boolean);
var
fn : string;
tf : tfileStream;
begin
fn := 'C:\inetpub\wwwroot\test.bin';
Response.Content := '';
Response.ContentType := 'application/octet-stream';
Response.CustomHeaders.Values['Content-Disposition'] := 'attachment; filename=test.bin';
tf := tfilestream.Create( fn, fmopenread or fmShareDenyWrite );
Response.ContentStream := tf;
handled := true;
end;
Ich setze hier zusätzlich auch noch den gewünschten Filenamen (muss natürlich nicht dem Filenamen auf dem Server entsprechen).