Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Netzwerke (https://www.delphipraxis.net/14-netzwerke/)
-   -   DataSnap mit REST und viele Daten (Stream) (https://www.delphipraxis.net/202718-datasnap-mit-rest-und-viele-daten-stream.html)

wjjw 2. Dez 2019 09:10

DataSnap mit REST und viele Daten (Stream)
 
Hallo!

Ich habe ein Problem bei der Übertragung großer Daten via DataSnap REST.
Die Daten sind Dateiinhalte, jedoch können auch andere Inhalte übertragen werden, da diese via Streams verschickt werden.
Bei "kleineren" Datenmengen (< 20MB) klappt alles wunderbar.
Werden die Daten (Dateien) größer, so bekomme ich immer ein "Out of memory".

Kann ich die Übertragung "stückeln" oder gibt es eine andere Lösung?
Die Frage was ist hier der richtige Weg.
Möchte/muss ja nicht den ganzen Stream in den Speicher laden, aber wie stelle ich das an.

Derzeit ist der (vereinfachte) Code wie folgt:

Delphi-Quellcode:
// Server
function TServerMethods1.GetStream(len: Int64; var ms: TStream): Boolean;
const buffer = 1024;
var m: TMemoryStream;
    a: Array[1..buffer] of Byte;
    cnt: Integer;
    rest: Int64;
begin
   Result := False;
   try
      FillChar(a, buffer, 'X');
      ms := TMemoryStream.Create;
      rest := len;
      while (rest > 0) do
      begin
         if (rest >= buffer) then cnt := buffer else cnt := rest;
         ms.Write(a, cnt);
         rest := rest - cnt;
      end;
      Result := True;
   except
      //
   end;
end;

// Client
procedure TForm1.Btn_GetStreamClick(Sender: TObject);
var i: Int64;
    erg: Boolean;
    ms: TStream;
begin
   i := StrToInt(Edit3.Text);  // 25184294
   ms := TMemoryStream.Create;
   erg := ClientModule1.ServerMethods1Client.GetStream(i, ms);
   if erg then Memo1.Lines.Add('Ok - ' +IntToStr(i)) else Memo1.Lines.Add('Fehler - ' +IntToStr(i));
end;

Der schöne Günther 2. Dez 2019 10:05

AW: DataSnap mit REST und viele Daten (Stream)
 
Ich kenne mich mit DataSnap nicht aus, sehe aber dass du gleich zwei Streams erstellst und sie niemals freigibst.

Ist das nicht im Endeffekt die gleiche Frage diese hier?

https://www.delphipraxis.net/191685-...ut-memory.html

wjjw 2. Dez 2019 10:54

AW: DataSnap mit REST und viele Daten (Stream)
 
Codebeispiel ist sehr gekürzt.
Mich würde nur interessieren, wie die Daten via REST und Stream übertragen werden.

Wenn ich 50GB versenden möchte, muss ich es "manuell" zerstückeln oder macht das DataSnap intern.
Soll heissen, muss ich eigene Pakete schnüren oder sollte das im Protokoll schon implementiert worden sein.
Macht für mich keinen Sinn 50GB zuerst in den Speicher einzulesen (wo ich sicher ein "Out of memory" bekomme) und dann auf einmal zu verschicken.
Hab diesbezüglich auch nichts gefunden (nur wie man (kleine) Bilder überträgt via Stream - das funktioniert ja eh ohne Probleme).

Rollo62 3. Dez 2019 05:59

AW: DataSnap mit REST und viele Daten (Stream)
 
Das ist vielleicht nicht die ganze Lösung, aber ein BufferedFileStream könnte helfen.
Weitere Anregungen:
https://delphiaball.co.uk/2016/04/29...redfilestream/
http://docwiki.embarcadero.com/Libra...mWriter.Create


Evtl. muss man das dann etwas verfeinern für deine Aufgabe.
Ansonsten denke ich das es aber auch auf dem Server eine Umstellung braucht, denn 50GB kann leicht abstürzen, und auch der Server sollte Chunks empfangen/senden und die Sendung/Empfang wieder aufnehmen können.

Sherlock 3. Dez 2019 07:51

AW: DataSnap mit REST und viele Daten (Stream)
 
Ich habe eine REST Anwendung und einen Apache-Python-Server, da stelle ich für große Streams das Objekt kurzfristig als Download bereit. Ist einfacher so. Ich hatte dann auch nicht mehr das Problem, daß ein Downloadfortschritt per REST nicht so ganz trivial umzusetzen ist (für mich).

Sherlock

himitsu 3. Dez 2019 10:30

AW: DataSnap mit REST und viele Daten (Stream)
 
Bei Streams die größer sind als der Übertragungspuffer, gibt es kein "Size", bzw. die ist -1, und damit kommen viele Codes nicht klar. (z.B. fast alle LoadFromStream, Stream.CopyTo usw.)

Bei uns hatte ich nach mehreren solcher Problemchen die DataSnap-Klassen abgeleitet und kopiere nach der Übertragung alles in einen MemoryStream, welchen ich dann zurück geben, anstatt des Streams vom DataSnap.


DataSnap-Streams kleiner 32 KB (glaub ich) sind komplett übertragen und bei mehr Daten (mit Size=-1) wird erst beim Auslesen der Inhalt übertragen, also so lange Auslesen bis das Read 0 Bytes liefert.

@Sherlock: Ich hatte Anangs auch einen TCP/IP-Server (Indy) parallel betrieben, bis wir das mit dem -1 endlich rausbekommen hatten. (nichtmal der Support von Embarcadero wusste es anfangs)

wjjw 4. Dez 2019 13:32

AW: DataSnap mit REST und viele Daten (Stream)
 
Das "komische" ist, das wenn ich einen "normalen" DataSnap Server mit der gleichen Funktion wie im DataSnap REST Server habe, es funktioniert.
Also via https "ohne" REST (via Wizard) klappt es problemlos - egal wie gross die Daten sind.

Konnte auch nirgendwo nachlesen, was der Unterschied zwischen "DataSnap Server" und "DataSnap REST Anwendung" ist (beide via http/https).
Auch die Aufrufe und Ergebnisse sind gleich, nur nicht bei Streams... :!:

himitsu 5. Dez 2019 11:13

AW: DataSnap mit REST und viele Daten (Stream)
 
Es kann sein dass das Protokoll intern anders arbeitet und Streams/binäre Daten in dem REST-Text anders gesteuert/übertragen werden.

DataSnap konnte damals vor allem Binär und JSON für die Übertragung nutzen (wenn ich mich Recht erinner) und wird jetzt wohl nicht viel anders sein. (REST = XML, aber vom Prinzip her ja eigentlich egal)


Aber ich muß nochmal betonen, dass wir hier ja unser eigenes System basierend auf den generierten DataSnap-Interfaces der ersten/zweiten Generation verwenden (die Klassen abgeleitet, umgebaut und erweitert um die "Bugfixes" für die Übertragung von Streams/DataSets), der Support damals selber nicht viel schnell/viel helfen konnte, bei dem was abweichend von den wirklich schön aussehenden und einfachen Funktion der Demoanwendungen, und ich nun keine große Lust mehr hatte, nach dem Streß mich seitdem weiterhin damit zu befassen.
Es läuft immernoch und ich werde mich hüten daran nochmal was zu verändern. (außer dass wir da eher noch Dinge wieder ausgebaut und auf andere Technologieen umgestiegen sind, vor allem was das Caching und Abrufen von DataSets aus unserem AppServer betrifft ... Die Synchronasitation für MultiUser/Multithreaded in Verbindung von PgDAC und DataSnap hatte viel Zeit gekostet)

Delphi XE: vorallem Probleme mit Streams und BLOB-Feldern in DataSets


Alle Zeitangaben in WEZ +1. Es ist jetzt 19:57 Uhr.

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