![]() |
DataSnap - Zugriff von WebProjekt
Falls jemand weiß wie man da mit JavaScript Binärdaten überträgt, wäre es schön zu wissen,
denn die bestehende Serverstruktur weiterverwenden zu können, für die neue zusätzliche Webanwendung, das wäre doch zu praktisch. * Dokumente abrufen und anzeigen (das Ginge) * Foto machen oder Datei einlesen und übertragen (das knallt) Also, damals vor vielen Jahren einen DataSnap-Server implementiert und bissl angepasst. Wir haben noch eine Zwischenschicht im DataSnap drin, welche beim Empfänger (Client und Server) die TStreams von dem blöden DataSnap-Stream in ein TMemoryStream umkopiert, weil viele Dinge mit dem Size=-1 nicht klar kommen, was bei größeren Streams ankommt, wenn DataSnap die Daten beim Auslesen stückweise nachlädt. Und auch TDataSets hatten wir damals nochmal überarbeitet, weil es bei größeren TEXTen Probleme gab, im Zusammenhang mit DevExpressGrids und dessen DataController. (TEXT in VARCHAR konvertiert, vor Übergabe in dem DBXDataSetStreamingzeugs, bzw. den Code kopiert und da die Typen ausgetauscht). Das lief bisher problemlos binär, also via TCP/IP (TDSTCPServerTransport2), bzw. intern mit dbExpress, und nun hatte noch den TDSHTTPService nachgerüstet. Aber dort habe ich nun Probleme beim Abruf. Erstmal wird die AuthentificationMethode doppelt aufgerufen und beim zweiten Mal mit NIL im Parameter (ist bekannt, denn viele hatten das Problem schon), was bissl blöd ist, wenn man auf den Parameter zugreift, um darin Nutzername und Passwort zu prüfen. (gut, da der erste Durchlauf ausreicht, überspring ich das einfach ... if not assigned then exit) Schlimmer ist aber, dass ich ums verrecken nicht alle Funktionen aufgerufen bekomme, vorallem da nicht wo in TStream reingegeben werden soll. [EDIT] Da hing wohl ein Haltepunkt etwas. Grade nochmal alles ohne Eurekalog kompiliert, und nun gesehen dass unsere TDSFileMethods.WriteFile erfolgreich aufgerufen und ausgeführt wird, aber nach dem END; der Methode knallt es dann irgendwo. [/EDIT] * Danke erstmal an Eurekalog, dass ihr einem ständig beim Debuggen das Leben erschwert. * nach Loswerden des Mistdings nun "irgendwo" die Fehlerstelle in der DataSnapServer150.bpl verordet, aber k.A. warum. (ja, der Umstieg auf 10.2 ähhh 10.3 10.4 ist schon geplant) Zuerst hab ich mir mal schnell eine Clientanwendung generieren lassen und wollte mir im Server das Protokoll loggen, um zu sehen was wie übergeben werden muß, aber leider knallt es jetzt schon. Beim Debuggen und aus dem generierten Client ist zu erkennen, dass "leider" der Stream als JSON via HTTP-POST übergeben werden muß. Gut, unser Webentwickler wäre damit schon zufrieden, falls ich es hinbekomm dass es funktioniert, und wenn man rausbekommt wie die Binärdaten da codiert werden müssen. Gefragt hatte er aber auch zuerst, ob wir z.b. auch MultiPart-POSTs als über einen REST-Serverannehmen können, wobei mir dann erstmal einfiel, dass DataSnap auch RESTful ist und so wollte ich erstmal schauen was damit geht, weil der schon da ist. Das Format des JSON, bzw. die zwei Möglichen der Parameterübergabe sind teilweise aus der Doku zu entnehmen, jedenfalls das grundlegende Format, aber nicht der einzelnen Datentypen. ![]() ![]() ![]() ![]() ![]() * Hab ich beide probiert, es knallte, also hab ich den TestClient neu generieren lassen. SO, hier die 3 Testfunktionen des DataSnap-Servers: [DELPHI]function TDSServerMethods.ReverseString(S: String): String; function TDSFileMethods.ReadFile(Filename: String): TStream; procedure TDSFileMethods.WriteFile(Filename: String; Stream: TStream);[DELPHI] Und Letztere knallt leider. Wenn nichts geht, muß ich wohl selbst codieren (z.B. Base64) und es als "String" übergeben lassen. Über https://apitester.com/ bissl rumprobiert:
Code:
GET /DataSnap/REST/TDSServerMethods/ReverseString/ABC12345 HTTP/1.1
Host: *****:8080 Accept: */* User-Agent: Mozilla/5.0 (compatible; Rigor/1.0.0; http://rigor.com) Authorization: Basic *****
Code:
oder
HTTP/1.1 200 OK
Connection: close Content-Type: text/html; charset=ISO-8859-1 Content-Length: 23 Pragma: dssession=305680.375499.525712,dssessionexpires=1200000 Server: DatasnapHTTPService/2011 {"result":["54321CBA"]}
Code:
GET /DataSnap/REST/TDSFileMethods/ReadFile/rechnung\1192.pdf HTTP/1.1
Host: pg.prodat-erp.de:8080 Accept: */* User-Agent: Mozilla/5.0 (compatible; Rigor/1.0.0; http://rigor.com) Authorization: Basic *****
Code:
GET-Abrufe funktionieren erstmal.
HTTP/1.1 200 OK
Connection: close Content-Type: text/html; charset=ISO-8859-1 Content-Length: 194106 Pragma: dssession=407731.981971.840684,dssessionexpires=1200000 Server: DatasnapHTTPService/2011 %PDF-1.7 %âãÏÓ 2 0 obj <</Length 3532/Filter/FlateDecode>> stream xÅ[Én$ǽ7ÐÿPg,çZ`4@Ž8|³=€‚n¶–€ÑÅ¿ï÷"2²*«ºÉ^†Ò¡Y[.±¼X23øõxøûñðõÜß4N½C7ø©Oƒïð˜¦.O}î~û÷ñðýñðëñðòåxøóg×Íýìº/ÿ9~ø±sÝ¿Ž‡‹ë~ûéxHSî‡Ô Cî3ÚàÛ_œ‹Ù¹ðìœÇÕGü\¹òž¿¿ñÔ}ùùxxÅ7Ì“Sï’ÍãÆ™ðÃu\ÞÛ¼r½kžú<*çq ;ƒîð#Cä#Ý5vô½6v!+òðéß|×\~î‡ÁæyQf¦‡¸Œ¹J ... Und ja, bemerkenswert ist, dass DataSnap immer von "text/html" redet, egal ob es REST/JSON oder Binärdaten ausliefert. Im Gegenzug ist es auch vollkommen egal, was ich als Content-Type übergeben, es wird immer als JSON interpretiert, denn wenn ich versuche es wie beim Abruf binär zu übergeben, dann
Code:
POST /DataSnap/REST/TDSFileMethods/%22WriteFile%22/rechnung%5C1192.pdf HTTP/1.1
Host: pg.prodat-erp.de:8080 Accept: */* User-Agent: Mozilla/5.0 (compatible; Rigor/1.0.0; [url]http://rigor.com[/url]) Authorization: Basic ***** Content-Type: application/octet-stream Content-Length: 194106 %PDF-1.7 %âãÏÓ 2 0 obj ...
Code:
also
HTTP/1.1 500 Interner Server-Fehler
Connection: close Content-Type: text/html; charset=ISO-8859-1 Content-Length: 93 Pragma: dssession=982145.594458.865431,dssessionexpires=1200000 Server: DatasnapHTTPService/2011 {"error":"JSON-Werteingabe %PDF-1.7.... kann nicht in TDBXTypes.UNKNOWN(33) konvertiert werden"}
Code:
oder
POST /DataSnap/REST/TDSFileMethods HTTP/1.1
Host: pg.prodat-erp.de:8080 Accept: */* User-Agent: Mozilla/5.0 (compatible; Rigor/1.0.0; http://rigor.com) Authorization: Basic ***** Content-Length: 88 Content-Type: application/x-www-form-urlencoded {"_parameters":["rechnung\\1192__.pdf", "123456789"]}
Code:
oder mit filename in der URI
...
{"filename":"rechnung\\1192__.pdf", "stream":"123456789"}
Code:
...
{"stream":"123456789"}
Code:
HTTP/1.1 500 Interner Server-Fehler
Connection: close Content-Type: text/html; charset=ISO-8859-1 Content-Length: 89 Pragma: dssession=144988.358193.280590,dssessionexpires=1200000 Server: DatasnapHTTPService/2011 Zugriffsverletzung bei Adresse 5003A116 in Modul 'rtl150.bpl'. Lesen von Adresse 00000001 Zitat:
[EDIT] Also unsere Methode ist durchgelaufen und nach dem END hab ich mich nun mühsam mit F7/F8 durchgekämpft. Im zweiten oder dritten Generis+xxx (DataSnapServer150.bpl) knallt es dann, scheinbar am Ende einer Methode, beim Freigeben eines "Records", im zweiten Eintrag, bei der Speicherfreigabe. EInvalidPointer (Ungültige Zeigeroperation) oft gefolgt von zwei oder drei dutzend Indy- und DBX-Exceptions. Zitat:
Im Moment weiß ich einfach nicht mehr weiter. Die Methoden mit dem TCPIP-Client funktionieren seit Jahren, aber über den HTTP-TunnelService raucht ein Teil grandios ab. Aus dem neuen Testclient
Delphi-Quellcode:
und der automatisch generierte Code dazu
procedure TForm1.Button1Click(Sender: TObject);
var X: TStream; S: string; begin { S := ClientModule1.DSServerMethodsClient.ReverseString('abc123'); if S = '321abc' then ; X := ClientModule1.DSFileMethodsClient.ReadFile('rechnung\1192.pdf'); if X.Size > 0 then ; X.Free; } S := '12345'; X := TMemoryStream.Create; X.Write(S[1], 10); X.Position := 0; ClientModule1.DSFileMethodsClient.WriteFile('rechnung\1192.pdf', X); X.Free; end;
Delphi-Quellcode:
POST ist also richtig
procedure TDSFileMethodsClient.WriteFile(Filename: string; Stream: TStream);
begin if FWriteFileCommand = nil then begin FWriteFileCommand := FConnection.CreateCommand; FWriteFileCommand.RequestType := 'POST'; FWriteFileCommand.Text := 'TDSFileMethods."WriteFile"'; FWriteFileCommand.Prepare(TDSFileMethods_WriteFile); end; FWriteFileCommand.Parameters[0].Value.SetWideString(Filename); FWriteFileCommand.Parameters[1].Value.SetStream(Stream, FInstanceOwner); FWriteFileCommand.Execute; end; und beim Debuggen von FWriteFileCommand.Execute ist zu erkennen, dass es als zwei Parameter in JASON verpackt wird. |
AW: DataSnap - Zugriff von WebProjekt
So, nach paar Tagen genervter Suche, endlich eine Lösung.
Ich hab mich nun mühevoll durch das Senden des DataSnap-HTTP/REST-Clienten gekämpft und geschaut was gesendet wird. Ja, es gibt eine nette Trace-Methode im Server, wo man das Protokoll loggen kann, allerdings wird die erst NACH der Verarbeitung aufgerufen, wo man dann Request und Response einsehen kann, aber da es schon vorher knallt und abraucht ......... TDSRestCommand.Execute ExecuteCommand (DSClientRest) ExecuteRequest (DSClientRest) LParametersToSendInContent:= ExecuteRequest> ParameterToJSon TDBXJSONTools.StreamToJSON Dabei ensteht ein JSON-Array mit sehr vielen Values/Integern pro Byte, locker 3 bis 4 Mal so viele Daten wie die Datei groß ist.
Delphi-Quellcode:
procedure TDSFileMethods.WriteFile(Filename: String; Stream: TStream);
Zitat:
Mit einem Delphi-Client könnte ich meine Lösung nicht umsetzen, da DataSnap alle String-Parameter ohne Längenprüfung in die URL einbaut (in XE) und nur Tabellen/Streams/Json als JSON via POST sendet (siehe ExecuteRequest und IsUrlParameter in DSClientRest), aber zum Glück kann man das bei manuellem REST-Aufruf das anpassen (eine beliebige Anzahl der Parameter in der URL und ab beliebiger Quelle geht's weiter im JSON-Request). Wichtig ist aber dass man Accept und Content-Type nicht vergisst, denn so wie im Response der Content-Type totaler Schwachsinn ist, darf man ihm im Request aber nicht vergessen, sonst werden die POST-Daten zwar zwangsweise als JSON entgegen genommen (oder es knallt) aber dann einfach still und heimlich ignoriert (POST-Parameter bleiben leer und TStream ist nil). Hab das mal mit ReverseString ausprobiert
Delphi-Quellcode:
function TDSServerMethods.ReverseString(S: String): String;
Zitat:
Zitat:
Zitat:
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 08:56 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-2025 by Thomas Breitkreuz