![]() |
Datenbank: DataSnap • Version: 12 • Zugriff über: SQLConnection + SQLServerMethod
Datei über DataSnap Verbindung senden
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:
und der Client ruft sie so auf:
function TDSServerModule1.GetFile(Filename: string): TMemoryStream;
begin Result := TMemoryStream.Create; Result.LoadFromFile(Filename); end;
Delphi-Quellcode:
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 :-D
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; |
AW: Datei über DataSnap Verbindung senden
Hänge grade am selben Problem. :cry:
Ich hab aber schon rausgefunden, daß man ![]() 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. |
AW: Datei über DataSnap Verbindung senden
Ich würde statt Datasnap direkt auf Indy zugreifen. Ich versende z.B. so einen Stream:
Delphi-Quellcode:
Und lese den Stream beim Client so ein:
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;
Delphi-Quellcode:
LG
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; Dirk |
AW: Datei über DataSnap Verbindung senden
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. :evil: |
AW: Datei über DataSnap Verbindung senden
ich war auch der meinung das beruht auf indy, oder liege ich da falsch?
|
AW: Datei über DataSnap Verbindung senden
Jupp, irgendwo im Inneren kommt dann Indy und ich glaub ein DataSet war auch irgendwo mit dabei.
|
AW: Datei über DataSnap Verbindung senden
Liste der Anhänge anzeigen (Anzahl: 2)
So, hab mich nun doch nochmal an Emba gewendet.
![]() 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. :warn: [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): |
AW: Datei über DataSnap Verbindung senden
Gut, das war's.
Hab mich nun mühevoll bis zur entscheidenden Stelle durchgedebuggt.
Delphi-Quellcode:
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.
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; 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) :?: |
Alle Zeitangaben in WEZ +1. Es ist jetzt 11:09 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz