AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Datenbanken Delphi Datei über DataSnap Verbindung senden
Thema durchsuchen
Ansicht
Themen-Optionen

Datei über DataSnap Verbindung senden

Ein Thema von WorstNightmare · begonnen am 5. Jan 2009 · letzter Beitrag vom 21. Jan 2011
Antwort Antwort
WorstNightmare

Registriert seit: 6. Okt 2008
159 Beiträge
 
RAD-Studio 2010 Arc
 
#1

Datei über DataSnap Verbindung senden

  Alt 5. Jan 2009, 20:51
Datenbank: DataSnap • Version: 12 • Zugriff über: SQLConnection + SQLServerMethod
Hallo,

ich "missbrauche" eine DataSnap Datenbank Verbindung für einen Remote-Explorer. Der Server läuft auf einem Rechner im Keller und der Client soll mir bestimmte Ordner auf seiner Festplatte anzeigen. Ich möchte nicht einfach normale Windows-Freigaben benutzen, da ich spezielle Shortcuts und andere Funktionen einbauen möchte. Nun bringt es mir nichts die Dateien einfach nur anzukucken, sondern würde ich sie auch gerne runter- und neue Inhalte hochladen.
Das Durchsuchen alleine klappt ganz gut, aber das Runterladen scheitert ab einer Dateigröße > 29 KB.
Die GetFile Methode auf dem Server sieht so aus:
Delphi-Quellcode:
function TDSServerModule1.GetFile(Filename: string): TMemoryStream;
begin
  Result := TMemoryStream.Create;
  Result.LoadFromFile(Filename);
end;
und der Client ruft sie so auf:
Delphi-Quellcode:
function TForm2.GetFile(Filename: string): Integer;
var
  Svr: TDSServerModule1Client;
begin
  Svr := TDSServerModule1Client.Create(SQLConnection1.DBXConnection);
  try
    Result := Svr.GetFile(Filename).Size;
  finally
    FreeAndNil(Svr);
  end;
end;
Und wiegesagt, wenn die angeforderte Datei > 29 KB, dann hat der MemoryStream eine Größe von -1. Lässt sich das irgendwie umgehen oder ist diese Datenbank einfach nicht dazu gemacht große Datenmengen aufeinmal zu übertragen? Ich möchte mich ungern mit Socketprotokollen etc. herumschlagen, diese Methode hier erscheint mir viel einfacher
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
43.142 Beiträge
 
Delphi 12 Athens
 
#2

AW: Datei über DataSnap Verbindung senden

  Alt 19. Jan 2011, 15:27
Hänge grade am selben Problem.

Ich hab aber schon rausgefunden, daß man Delphi-Referenz durchsuchenTDSTCPServerTransport.BufferKBSize auch ändern kann.
Durch dieses stehen für eine Übertragung insgesammt nur diese Datenmenge zur Verfügung.

29 KB + die restlichen Felder und Zusatzdaten <= BufferKBSize


Nun kann man BufferKBSize zwar maximal auf 1000 setzen (also ~0,98 MB, wobei diese Grenze in der OH natürlich wiedermal nicht drinsteht).

Aber dennoch kommt bei mir ein Stream (TIFF) mit nur 160 KB einfach nicht an, wärend es eine knapp 800 KB Textdatei schafft.
hatte mich wohl vermessen



Nun die Frage(n):

Warum kommen nicht alle Dateien durch?

Und wieso wirft das blöde DataSnap keine Fehlermeldung, wenn der Stream zu groß ist?


[edit]
Eigentlich dachte ich erst, daß DataSnap mit irgendwelchen Bytes/Bytefolgen in der Binärdatei nicht klarkommt, aber es liegt einfach nur daran, daß Dateien ab genau 64 KB (also >= 64KB) ebenfalls nicht durchkommen.
Also selbst wenn man BufferKBSize bis auf 1000 KB hochsetzen kann, muß ein Stream dennoch kleiner als 64 KB sein.
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests

Geändert von himitsu (19. Jan 2011 um 16:30 Uhr)
  Mit Zitat antworten Zitat
Piethan

Registriert seit: 2. Jun 2008
Ort: Köln
43 Beiträge
 
Delphi XE Architect
 
#3

AW: Datei über DataSnap Verbindung senden

  Alt 19. Jan 2011, 17:26
Ich würde statt Datasnap direkt auf Indy zugreifen. Ich versende z.B. so einen Stream:

Delphi-Quellcode:
begin
                  sinput:=IOHandler.ReadLn;
                  try
                     memo1.Lines.Add('Lade: '+sinput);
                     dm_vvk.cs_get_user.Params.ParamByName('iuser').AsString:=sinput;
                     dm_vvk.cs_get_user.Open;
                     stream := TMemoryStream.Create;
                     vtable:= TVirtualTable.Create(self);
                     vtable.Assign(dm_vvk.cs_get_user);
                     buf:=nil;
                     vtable.SaveToStream(stream,True);
                     IOHandler.Write(stream,0,true);
                     buf:= nil;
                     vtable.Free;
                     stream.Free;
                  finally

                  end;
Und lese den Stream beim Client so ein:

Delphi-Quellcode:
    stream:= TMemoryStream.Create;
    abuf:= nil;
    IdTCPClient1.IOHandler.WriteLn('3');
    IdTCPClient1.IOHandler.WriteLn(aactuser.username);
    IdTCPClient1.IOHandler.ReadStream(stream);
    Vtuser.LoadFromStream(stream,true);
    Vtuser.Active:=true;
    stream.Clear;
LG
Dirk
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
43.142 Beiträge
 
Delphi 12 Athens
 
#4

AW: Datei über DataSnap Verbindung senden

  Alt 20. Jan 2011, 08:14
Nja, DataSnap ist halt soooooo cool und new-style, da wollten wir es mal ausprobieren.

Es kann doch nicht sein, daß soein hochbeworbenes Produkt derartig beschränkt und fehleranfällig ist.

Wenn es aber so gedacht ist, dann sollte man wenigstens solche Beschränkungen auch nennen und mit entsprechenden Fehlermeldungen behandeln.
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests
  Mit Zitat antworten Zitat
DSCHUCH

Registriert seit: 6. Jun 2007
Ort: Dresden
185 Beiträge
 
Delphi 10.2 Tokyo Enterprise
 
#5

AW: Datei über DataSnap Verbindung senden

  Alt 20. Jan 2011, 11:36
ich war auch der meinung das beruht auf indy, oder liege ich da falsch?
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
43.142 Beiträge
 
Delphi 12 Athens
 
#6

AW: Datei über DataSnap Verbindung senden

  Alt 20. Jan 2011, 11:57
Jupp, irgendwo im Inneren kommt dann Indy und ich glaub ein DataSet war auch irgendwo mit dabei.
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
43.142 Beiträge
 
Delphi 12 Athens
 
#7

AW: Datei über DataSnap Verbindung senden

  Alt 20. Jan 2011, 16:05
So, hab mich nun doch nochmal an Emba gewendet.
http://qc.embarcadero.com/wc/qcmain.aspx?d=90995

Ich liebe dieses vor Datenschutz mangelnde Meldesystem, welches den Post löscht und man alle neu schreiben müßte, wenn man nicht schnell genug schreibt, bevor man wieder ausgeloggt wird.
Und wenn sich wer über das größtenteils Goggle-Translate-Englisch beschwert, dann steige ich wieder auf den Babelfish um.

[add]
noch 'ne kleine Demoanwendung

Code:
Size of Stream (0 = Exit, -1 = basic tests): -1

ServerMethods1Client.SendToServer
  Data.ClassName = TMemoryStream
  Data.Size     = 0

ServerMethods1Client.ReciveFromServer
  Result.ClassName = TDBXBytesStream
  Result.Size     = 0 (0)

ServerMethods1Client.SendToServer
  Data.ClassName = TMemoryStream
  Data.Size     = 100

ServerMethods1Client.ReciveFromServer
  Result.ClassName = TDBXBytesStream
  Result.Size     = 100 (100)

ServerMethods1Client.SendToServer
  Data.ClassName = TMemoryStream
  Data.Size     = 29000

ServerMethods1Client.ReciveFromServer
  Result.ClassName = TDBXBytesStream
  Result.Size     = 29000 (29000)

ServerMethods1Client.SendToServer
  Data.ClassName = TMemoryStream
  Data.Size     = 32000

ServerMethods1Client.ReciveFromServer
  Result.ClassName = TDBXStreamReaderStream
  Result.Size     = -1 (32000)

ServerMethods1Client.SendToServer
  Data.ClassName = TMemoryStream
  Data.Size     = 64000

ServerMethods1Client.ReciveFromServer
  Result.ClassName = TDBXStreamReaderStream
  Result.Size     = -1 (64000)

ServerMethods1Client.SendToServer
  Data.ClassName = TMemoryStream
  Data.Size     = 1000000

ServerMethods1Client.ReciveFromServer
  Result.ClassName = TDBXStreamReaderStream
  Result.Size     = -1 (1000000)

Size of Stream (0 = Exit, -1 = basic tests):

Code:
Starting TServerContainer1
Press ESC to stop the server

TServerMethods1.SendToServer
  Data.ClassName = TDBXBytesStream
  Data.Size     = 0 (0)

TServerMethods1.ReciveFromServer
  Result.ClassName = TMemoryStream
  Result.Size     = 0

TServerMethods1.SendToServer
  Data.ClassName = TDBXBytesStream
  Data.Size     = 100 (100)

TServerMethods1.ReciveFromServer
  Result.ClassName = TMemoryStream
  Result.Size     = 100

TServerMethods1.SendToServer
  Data.ClassName = TDBXBytesStream
  Data.Size     = 29000 (29000)

TServerMethods1.ReciveFromServer
  Result.ClassName = TMemoryStream
  Result.Size     = 29000

TServerMethods1.SendToServer
  Data.ClassName = TDBXStreamReaderStream
  Data.Size     = -1 (32000)

TServerMethods1.ReciveFromServer
  Result.ClassName = TMemoryStream
  Result.Size     = 32000

TServerMethods1.SendToServer
  Data.ClassName = TDBXStreamReaderStream
  Data.Size     = -1 (64000)

TServerMethods1.ReciveFromServer
  Result.ClassName = TMemoryStream
  Result.Size     = 64000

TServerMethods1.SendToServer
  Data.ClassName = TDBXStreamReaderStream
  Data.Size     = -1 (1000000)

TServerMethods1.ReciveFromServer
  Result.ClassName = TMemoryStream
  Result.Size     = 1000000










und wenn ServerContainerUnit.TServerContainer1.DSTCPServerT ransport1.BufferKBSize auf 1000 gesetzt ist, dann sieht es so aus:
Code:
**************************************************
*** Client ***************************************
**************************************************

Starting TServerContainer1
Press ESC to stop the server

TServerMethods1.SendToServer
  Data.ClassName = TDBXBytesStream
  Data.Size     = 0 (0)

TServerMethods1.ReciveFromServer
  Result.ClassName = TMemoryStream
  Result.Size     = 0

TServerMethods1.SendToServer
  Data.ClassName = TDBXBytesStream
  Data.Size     = 100 (100)

TServerMethods1.ReciveFromServer
  Result.ClassName = TMemoryStream
  Result.Size     = 100

TServerMethods1.SendToServer
  Data.ClassName = TDBXBytesStream
  Data.Size     = 29000 (29000)

TServerMethods1.ReciveFromServer
  Result.ClassName = TMemoryStream
  Result.Size     = 29000

TServerMethods1.SendToServer
  Data.ClassName = TDBXStreamReaderStream
  Data.Size     = -1 (32768)

TServerMethods1.ReciveFromServer
  Result.ClassName = TMemoryStream
  Result.Size     = 32768

TServerMethods1.SendToServer
  Data.ClassName = TDBXStreamReaderStream
  Data.Size     = -1 (65535)

TServerMethods1.ReciveFromServer
  Result.ClassName = TMemoryStream
  Result.Size     = 65535

TServerMethods1.SendToServer
  Data.ClassName = TDBXStreamReaderStream
  Data.Size     = -1 (65536)

TServerMethods1.ReciveFromServer
  Result.ClassName = TMemoryStream
  Result.Size     = 65536

TServerMethods1.SendToServer
  Data.ClassName = TDBXStreamReaderStream
  Data.Size     = -1 (1000000)

TServerMethods1.ReciveFromServer
  Result.ClassName = TMemoryStream
  Result.Size     = 1000000



**************************************************
*** Server ***************************************
**************************************************

Size of Stream (0 = Exit, -1 = basic tests): -1

ServerMethods1Client.SendToServer
  Data.ClassName = TMemoryStream
  Data.Size     = 0

ServerMethods1Client.ReciveFromServer
  Result.ClassName = TDBXBytesStream
  Result.Size     = 0 (0)

ServerMethods1Client.SendToServer
  Data.ClassName = TMemoryStream
  Data.Size     = 100

ServerMethods1Client.ReciveFromServer
  Result.ClassName = TDBXBytesStream
  Result.Size     = 100 (100)

ServerMethods1Client.SendToServer
  Data.ClassName = TMemoryStream
  Data.Size     = 29000

ServerMethods1Client.ReciveFromServer
  Result.ClassName = TDBXBytesStream
  Result.Size     = 29000 (29000)

ServerMethods1Client.SendToServer
  Data.ClassName = TMemoryStream
  Data.Size     = 32768

ServerMethods1Client.ReciveFromServer
  Result.ClassName = TDBXBytesStream
  Result.Size     = 32768 (32768)

ServerMethods1Client.SendToServer
  Data.ClassName = TMemoryStream
  Data.Size     = 65535

ServerMethods1Client.ReciveFromServer
  Result.ClassName = TDBXBytesStream
  Result.Size     = 65535 (65535)

ServerMethods1Client.SendToServer
  Data.ClassName = TMemoryStream
  Data.Size     = 65536

ServerMethods1Client.ReciveFromServer
  Result.ClassName = TDBXStreamReaderStream
  Result.Size     = -1 (65536)

ServerMethods1Client.SendToServer
  Data.ClassName = TMemoryStream
  Data.Size     = 1000000

ServerMethods1Client.ReciveFromServer
  Result.ClassName = TDBXStreamReaderStream
  Result.Size     = -1 (1000000)

Size of Stream (0 = Exit, -1 = basic tests):
Angehängte Dateien
Dateityp: rar DataSnap-StreamTest.rar (1,59 MB, 6x aufgerufen)
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests

Geändert von himitsu (21. Jan 2011 um 12:24 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
43.142 Beiträge
 
Delphi 12 Athens
 
#8

AW: Datei über DataSnap Verbindung senden

  Alt 21. Jan 2011, 14:26
Gut, das war's.

Hab mich nun mühevoll bis zur entscheidenden Stelle durchgedebuggt.
Delphi-Quellcode:
function TDBXRowBuffer.WriteBytes(const Reader: TDBXStreamReader): Integer;
var
  Count: Integer;
begin
  if (FOff + TDBXFieldHeader.FBigHeaderLength + FMaxInline) > FBufLength then
    Growbuf(TDBXFieldHeader.FBigHeaderLength + FMaxInline);
  Count := Reader.Read(FBuf, FOff + TDBXFieldHeader.FBigHeaderLength, AvailableInline);
  if Count < 1 then
    FBuf[IncrAfter(FOff)] := Byte((TDBXFieldHeader.FTinyField))
  else
  begin
    if Reader.Eos then
      FBuf[FOff] := Byte((TDBXFieldHeader.FBigField))
    else
      FBuf[FOff] := Byte((TDBXFieldHeader.FBigField + TDBXFieldHeader.FPositive));
    FBuf[FOff + 1] := Byte(((Count shr 8) and 255));
    FBuf[FOff + 2] := Byte(((Count) and 255));
    FOff := FOff + Count + TDBXFieldHeader.FBigHeaderLength;
  end;
  Result := Count;
end;
AvailableInline begrenzt den Stream so, daß er in den Übertragungspuffer (BufferKBSize) reinpaßt und daß dieser kleiner als 64 KB ist, da es nur 2 Byte für die Längenangabe gibt.

Heißt also, daß standardmäßig nur ~29 KB und maximal nur 64 KB pro Stream zur Verfügung stehen.

Eine passende Fehlermeldung oder ein Hinweis in der Dokumentation hätte das Ganze bestimmt vereinfacht.




Bleibt jetzt nur die Frage, ob man den Stream nur in kleine Stückchen aufteilen und dieses dann einzeln versenden/abrufen soll, oder ob man den Stream über eine alternative Route verschickt (würde da aber gerne die Datenverbindung vom DataSnap nutzen)
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests

Geändert von himitsu (21. Jan 2011 um 14:52 Uhr)
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 09:32 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