Delphi-PRAXiS
Seite 1 von 2  1 2   

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Netzwerke (https://www.delphipraxis.net/14-netzwerke/)
-   -   Datasnap REST im Apache, Download einer Datei dauert sehr lange (https://www.delphipraxis.net/180801-datasnap-rest-im-apache-download-einer-datei-dauert-sehr-lange.html)

florian89 18. Jun 2014 15:16

Datasnap REST im Apache, Download einer Datei dauert sehr lange
 
Ich möchte über meinen REST-Webservice, den ich in einen Apache als ISAPI.dll eingebunden habe, Dateien herunterladen. Das klappt soweit, nur dauert es sehr lange.
Eine Datei (ca. 35 MB) wird aus einer Datenbank geholt und an den Client übertragen. Das dauert ca. 70 Sekunden, wenn ich die Methode des Webservice lokal aufrufe. (Übers Internet dauert es so ca. 5 Minuten!!!). Ca. 1-2 Sekunden dauert es, dann ist die Datei aus der Datenbank geholt.
Die Übertragung findet als String statt. Habe es auch schon per TStream probiert. Dauert aber genauso lang.

Hier meine Server-Methode:
Delphi-Quellcode:
function TServerMethods1.GetFile(aFile, version: string): string;
var
  stream: TMemoryStream;
begin
  stream := nil;
  result := '-1';
  try
    stream := GetFile(aFile, version);
    if stream.Size > 0 then
    begin
      StringToLogfile(logFileInfo, 'GetFile: Datei ' + aFile+ ' wurde gefunden');
      result := string(EncodeBase64(stream.Memory, stream.Size));
    end else
    begin
      StringToLogfile(logFileError, 'GetFile: Datei ' + aFile+ ' nicht gefunden');
      result := '-1814';
    end;
  finally
    stream.Clear;
    stream.Free;
  end;
end;
Kann mir jemand weiterhelfen?
Vielen Dank schon mal im Voraus!

mkinzler 18. Jun 2014 15:21

AW: Datasnap REST im Apache, Download einer Datei dauert sehr lange
 
Was für eine Zugang zum Internet hast Du? Grundsätzlich ist das ja nicht zu langsam (Upload).

himitsu 18. Jun 2014 15:25

AW: Datasnap REST im Apache, Download einer Datei dauert sehr lange
 
Base64 ist 1/3-tel größer, wie die Originaldaten, und ~46 MB zu übertragen dauert halt ein paar Sekündchen. (REST sollte das auch nicht als Unicode übertragen, sonst wäre es nochmal so viel)

Bei 5 Minuten wäre das dann ein Up-/Download von 1,2 MBit/s (falls ich mich nicht verschätzt hab)

florian89 18. Jun 2014 15:30

AW: Datasnap REST im Apache, Download einer Datei dauert sehr lange
 
Ca. 50.000 kB Download und 23.000 kB Upload
Wenn ich das ganze lokal teste, sollte das aber innerhalb von Sekunden geschehen oder?

mkinzler 18. Jun 2014 15:45

AW: Datasnap REST im Apache, Download einer Datei dauert sehr lange
 
Zitat:

Zitat von florian89 (Beitrag 1262796)
Ca. 50.000 kB Download und 23.000 kB Upload
Wenn ich das ganze lokal teste, sollte das aber innerhalb von Sekunden geschehen oder?

50MB oder 50MBit?

In einem Windowsnetz kann man von von ca. 8MB/s bei einem 100MBit-Netz ausgehen, dann sollten die Daten in ein paar Sekunden übertragen sein. Du überträgst Sie aber nicht direkt, sondern wandelst diese zuerst in einen String um. Warum streamst Du diese nicht direkt an den Client?

himitsu 18. Jun 2014 15:47

AW: Datasnap REST im Apache, Download einer Datei dauert sehr lange
 
[add]
Zitat:

Warum streamst Du diese nicht direkt an den Client?
Wir hatten das Anfangs auch parallel zum DataSnap via Indy (TCP) übertragen und über DataSnap nur die Übertragung gesteuert. (Teilweise über DataSnap-Callbacks)
Aber als wir dann rausfanden, warum größere Dateien "nicht" übertragen wurden (falsche Auswertung des Streams), baute ich das dann wieder so um, daß es jetzt nur noch via DataSnap läuft.
[/add]


PS: (Ob das wirklich bei REST geht, weiß ich nicht ... ich glaub wir verwenden JSON oder so ... hab's jetzt nicht mehr im Kopf)

Delphi-Quellcode:
function TServerMethods1.GetFile(Filename, Version: string): TStream;
begin
  Result := GetFile(Filename, Version);
  if Result.Size <= 0 then begin
    Result.Free;
    StringToLogfile(logFileError, 'GetFile: Datei ' + Filename + ' nicht gefunden');
    raise Exception.Create('GetFile: Datei ' + Filename + ' nicht gefunden');
  end;
  StringToLogfile(logFileInfo, 'GetFile: Datei ' + Filename + ' wurde gefunden');
end;
Auf Clientseite bekommt man da eine Art TMemoryStream an ('ne eigene Klasse des DataSnap), welchen man automatisch vom DataSnap freigeben lassen kann (dem automatisch generierten Client-Modul) oder man gibt es dann selber frei, wenn man es ausgelesen hat.

Delphi-Quellcode:
// Auf Serverseite, wenn man da einen Stream hin überträgt (automatische Freigabe):
procedure TDSFileMethods.Xyz(Stream: TStream);
begin
  ...
  MachWas(Stream);
  ...
end;

// Auf Clientseite, wenn ein Stream abgerufen wurde (manuelle Freigabe):
var
  Stream: TStream;
begin
  Stream := DataSnapClientModul.GetStream(...);
  try
    ...
    MachWas(Stream);
    ...
  finally
    Stream.Free;
  end;
end;

// Auf Clientseite, wenn ein Stream abgerufen wurde (automatische Freigabe):
var
  Stream: TStream;
begin
  Stream := DataSnapClientModul.GetStream(...);
  ...
  MachWas(Stream);
  ...
end;
Aber wenn du den Stream an eine Komponente weitergeben willst, dann empfehle ich dir den im Clienten umzukopieren, bevor er benutzt wird, denn .Size funktioniert nicht.
Delphi-Quellcode:
procedure FileMethods_CopyStream(Source, Dest: TStream);
var
  B: array[1..64*1024] of Byte;
  i: Integer;
begin
  Source.Position := 0;
  repeat
    i := Source.Read(B, SizeOf(B));
    Dest.WriteBuffer(B, i);
  until i < SizeOf(B);
end;

// Auf Serverseite, wenn man da einen Stream hin überträgt (automatische Freigabe):
procedure TDSFileMethods.Xyz(Stream: TStream);
var
  Temp: TStream;
begin
  Temp := TMemoryStream.Create;
  try
    FileMethods_CopyStream(Stream, Temp);
    ...
    MachWas(Temp);
    ...
  finally
    Temp.Free;
  end;
end;

// Auf Clientseite, wenn ein Stream abgerufen wurde (manuelle Freigabe):
var
  Temp, Stream: TStream;
begin
  Temp := TMemoryStream.Create;
  try
    Stream := DataSnapClientModul.GetStream(...);
    try
      FileMethods_CopyStream(Stream, Temp);
    finally
      Stream.Free;
    end;
    ...
    MachWas(Temp);
    ...
  finally
    Temp.Free;
  end;
end;

// Auf Clientseite, wenn ein Stream abgerufen wurde (automatische Freigabe):
var
  Temp: TStream;
begin
  Temp := TMemoryStream.Create;
  try
    FileMethods_CopyStream(DataSnapClientModul.GetStream(...), Temp);
    ...
    MachWas(Temp);
    ...
  finally
    Temp.Free;
  end;
end;

florian89 18. Jun 2014 15:50

AW: Datasnap REST im Apache, Download einer Datei dauert sehr lange
 
50 MBit
Ich verscuhe das ganze morgen mal per TStream und werde dann Bescheid geben

himitsu 18. Jun 2014 16:10

AW: Datasnap REST im Apache, Download einer Datei dauert sehr lange
 
Nja, das macht dann so maximal 5-7 MByte/s und dazu dann noch der Weg durchs Netz.
Und was hat die Gegenseite?


Und, du kannst problemlos Exceptions benutzen, denn DataSnap überträgt sie auch.


Ich hab nochmal einen meiner Threads rausgekramt.
http://www.delphipraxis.net/158379-w...ml#post1108637 #17

Bis standardmäßig 29KB lassen sich Streams problemlos übertragen.
Der Übertragungspuffer ist per Default 32 KB groß und alles was größer ist, wird gestückelt.

Stream.Size liefert dabei nur noch -1 und man muß/kann dann nur noch "blind" einlesen, bis zum Stream-Ende.
Im Notfall kann man sich eventuell per Var-Parameter noch die Streamgröße mit übertragen, damit man die Größe prüfen kann. (das hab ich bei uns aber nicht und es läuft dennoch)
Delphi-Quellcode:
function TServerMethods1.GetFile(Filename, Version: string; var StreamSize: Integer): TStream;

Delphi-Quellcode:
procedure TServerMethods1.PutFile(Filename, Version: string; Stream: TStream; StreamSize: Integer);

Elvis 18. Jun 2014 22:12

AW: Datasnap REST im Apache, Download einer Datei dauert sehr lange
 
Zitat:

Zitat von himitsu (Beitrag 1262805)
Im Notfall kann man sich eventuell per Var-Parameter noch die Streamgröße mit übertragen, damit man die Größe prüfen kann.

Warum benutzen ständig Leute var wenn sie out meinen? :|

himitsu 18. Jun 2014 22:42

AW: Datasnap REST im Apache, Download einer Datei dauert sehr lange
 
Weil Viele das Out nicht kennen?

Nja, ich denk oft nicht dran und im Delphi ist es meistens egal (außer daß beim Out hoffentlich der Compiler vorher keine "nicht initialisiert"-Meldung wirft?)
Aber hier hast'e schon Recht, im Prinzip ist es natürlich sinnlos, wenn der Parameter bei der Anfrage mit übertragen wird, obwohl man nur die Rückgabe braucht.


Und in Verbindung mit Interfaces hatte ich ein paar nette Speicherlecks kennengelernt.


Alle Zeitangaben in WEZ +1. Es ist jetzt 03:39 Uhr.
Seite 1 von 2  1 2   

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz