![]() |
AW: Indy HTTPClient Post umlaute
Zitat:
Hier der Code, also der Kern. Alles zu posten ist was lang. Indy:
Delphi-Quellcode:
ICS:
pdata:=TStringList.Create;
for i:=0 to memoPost.Lines.Count-1 do begin pdata.Add(UTF8Encode(memoPost.Lines.Strings[i])); end; try line:=HTTPClient.Post(URL,pdata); except i:=1; end; memoAnswer.Lines.Text:=line;
Delphi-Quellcode:
ICS ging auf anhieb. Und wie gesagt ich denke das ich die gebuggte Version von Indy habe. Ich habe vor Jahren mal Indy 10.6.0 Installiert. Nun wo man es weiß, sollte ich das mal updaten. Man kann ja auch mit Wireshark sehen das Indy das falsch übergibt. Indy macht ja die ? rein.
SndStrm := TMemoryStream.Create;
RcvStrm := TMemoryStream.Create; Data := UTF8Encode(memoPost.Lines.Text); HttpCli1.SendStream := SndStrm; HttpCli1.SendStream.Write(Data[1],Length(Data)); HttpCli1.SendStream.Seek(0,0); HttpCli1.RcvdStream := RcvStrm; HttpCli1.URL := URL; HttpCli1.Post; RcvStrm.Position:=0; memoAnswer.Lines.LoadFromStream(RcvStrm); memoAnswer.Lines.Add('....'); RcvStrm.Free; SndStrm.Free; |
AW: Indy HTTPClient Post umlaute
Das stimmt, mit dem UTF8Encode kommt es falsch an. Es sei denn ich lese es auf dem Server auch wieder als UTF-8 ein:
Delphi-Quellcode:
Der Grund ist simpel:
<?php
print_r(mb_convert_encoding($_POST, 'ISO-8859-1', 'UTF-8')); ?> Du kodierst es zwar als UTF-8, teilst das aber nicht mit. ICS wiederum verwendet UTF-8 Encoding als Standard, weshalb du das dort nicht explizit setzen musst. Korrekt mit Indy ist daher:
Delphi-Quellcode:
pdata:=TStringList.Create;
for i:=0 to memoPost.Lines.Count-1 do begin pdata.Add(UTF8Encode(memoPost.Lines.Strings[i])); end; try HTTPClient.Request.ContentEncoding := 'UTF-8'; line:=HTTPClient.Post(URL,pdata); except i:=1; end; memoAnswer.Lines.Text:=line; |
AW: Indy HTTPClient Post umlaute
Hi, bitte steck da keine Zeit mehr rein.
Delphi-Quellcode:
HTTPClient.Request.ContentEncoding := 'UTF-8';
Das habe ich alles versucht. Bevor ich hier Frage, kannst du davon ausgehen das ich mind. 2 Tage versuche das selber zu lösen. Und ja, das php gibt UTF-8 zurück und nimmt es an. Ich danke dir trotzdem Tausend mal für deine Hilfe und mühe. :thumb: |
AW: Indy HTTPClient Post umlaute
Delphi-Quellcode:
jaenicke ich habe
procedure libretranslate_Indy;
var json : rawbytestring; line : WideString; Stream: TStream; begin Stream := TMemoryStream.Create; try json := UTF8Encode('{ "q": "anöa","source": "auto", "target": "en", "api_key": ""}'); Stream.WriteBuffer(Pointer(json)^, Length(json)); Stream.Position := 0; form103.idhttp1.Request.ContentType := 'application/json'; line := UTF8Decode(form103.idhttp1.Post('http://127.0.0.1:5000/translate',stream)); // line:=form103.idhttp1.Post('http://httpbin.org/anything',pdata); Showmessage( line ); finally stream.Free; end; end; ![]() ![]() Sogar das funktioniert: json := UTF8Encode('{ "q": "أرى الكلب الأزرق الصغير خلف المنزل الأصفر على النهر الأحمر.","source": "auto", "target": "en", "api_key": ""}'); |
AW: Indy HTTPClient Post umlaute
Hi,
du musst auf jeden fall hoForceEncodeParams auf False setzen. Nachtrag: Nimm doch ICS, klappt auf anhieb. Ich habe grade mal Indy 10.6.3.1 Installiert. Selber Fehler. |
AW: Indy HTTPClient Post umlaute
Der Code in #24 funktioniert.
Ich nutze Indy sonst nicht - nur weil du gefragt hast, habe ich das Ding wieder einmal angeschaut - und es reicht wieder für ein paar Wochen. Ich nutze ICS. Fürs Posten setze ich wohl häufiger TNetHTTPClient, weil diese Komponente direkt mit den Sicherheitsfunktionen (https Unterstützung ohne "Basteln") von Windows interagiert. Herzlichen Dank für deinen Supertipp "libretranslate" - kannte ich nicht, ist grossartig und es fallen mir viele Dinge ein, welche ich tun würde, wenn ich mehr Zeit hätte... Dein Tipp "hoForceEncodeParams entfernen" gilt fürs Post mit zweitem Parameter TStringList, da sonst die Daten nur im HTTP Header landen und von libretranslate nicht "gesehen" werden (Bad request). Für post via Stream spielt die Option keine Rolle. Stream wird (wie von libretranslate gewünscht) im Body übertragen. Wenn ich den Indy Code anschaue, glaube ich, dass das Posten in diesem Fall mit TStrings nicht klappen kann. Wünsche wie Request.CharSet := 'utf-8'; Request.ContentEncoding := 'utf-8' oder utf8 beim Post als dritten Parameter setzen werden von Indy nicht berücksichtigt. Indy behandelt die von dir beim Post als zweiten Parameter übergebene TStringList als Parameter vom Typ par1=val1&par2=val2.... und codiert diese entsprechend via URLEncode. Die ?, welche du gesehen hast waren "nicht druckbare" Zeichen; HEX Monitor nutzen wäre hier u.U. aufschlussreicher. Fiddler ist übrigens grossartig, wenn du http Traffic untersuchen willst. Kurz: Beim Posten der json Daten statt TStrings einen Stream verwenden löst das Problem. Ich habe in #24 TMemorystream verwendet. Viel schöner ist es mit einem TStringStream (Copilot hat dies übrigens vorgeschlagen, als ich fragte, ob man den Code vereinfachen oder schöner schreiben könne.) Ich habe nun auch eine Fehlerbehandlung (ich habe Copilot nicht gefragt was KI davon hält ;-)) eingebaut:
Delphi-Quellcode:
oder via TNetHTTPClient (SSL Unterstützung)
function fehler : string;
var fehlermeldung : PCHar; begin getmem( fehlermeldung , 600 ); ExceptionErrorMessage( ExceptObject, ExceptAddr, fehlermeldung, 599 ); Result := fehlermeldung; end; function libretranslate_Indy(uebersetze : string; var uebersetzung : string ) : boolean; // RESULT=false, wenn eine Exception aufgetreten ist // Bei RESULT=false wird in uebersetzung die Fehlermeldung übergeben // Bei RESULT=true wird in übersetzung die Serverantwort von libretranslate zurückgeben. var JsonToSend : TStringStream; idhttp : TIdHTTP; begin Result := false; try JsonToSend := TStringStream.Create(uebersetze, TEncoding.UTF8); idhttp := TIdHTTP.Create(nil); try idhttp.Request.ContentType := 'application/json'; uebersetzung := UTF8Decode(idhttp.post('http://127.0.0.1:5000/translate',jsontosend)); Result := true; finally jsontosend.free; idhttp.Free; end; except uebersetzung := fehler; Result := false; end; end;
Delphi-Quellcode:
procedure WriteStringToStream(Stream: TStream; const Str: String);
var Data: TBytes; begin Data := TEncoding.UTF8.GetBytes(Str); Stream.WriteBuffer(Data[0], Length(Data)); end; function CreateHTTPClient: TNetHTTPClient; begin Result := TNetHTTPClient.Create(nil); end; function CreateHTTPRequest(Client: TNetHTTPClient): TNetHTTPRequest; begin Result := TNetHTTPRequest.Create(nil); Result.Client := Client; Result.CustomHeaders['Content-Type'] := 'application/json'; end; function CreateParamsStream(const Str: String): TStream; begin Result := TMemoryStream.Create; WriteStringToStream(Result, Str); Result.Position := 0; end; (* SSL/TLS-Details abstrahiert; interagiert direkt mit den Windows-Sicherheitsfunktionen *) procedure Uebersetze; var HTTPClient: TNetHTTPClient; HTTPRequest: TNetHTTPRequest; Params: TStream; Response: IHTTPResponse; begin HTTPClient := CreateHTTPClient; HTTPRequest := CreateHTTPRequest(HTTPClient); Params := CreateParamsStream(atest); try Response := HTTPRequest.Post('http://127.0.0.1:5000/translate', Params); ShowMessage(Response.ContentAsString(TEncoding.UTF8)); finally HTTPRequest.Free; HTTPClient.Free; Params.free; end; end; |
AW: Indy HTTPClient Post umlaute
Hi,
sowas sollte man sich mit Wireshark ansehen. Hier mal kurz. Indy mit hoForceEncodeParams
Code:
Das würde normalerweise wieder zusammen gebastelt. Aber Libre kann bzw. macht das nicht.
POST /translate HTTP/1.0
Connection: keep-alive Content-Encoding: UTF-8 Content-Type: application/json Content-Length: 167 Host: translate.lan:5000 Accept: application/json Accept-Charset: UTF-8 Accept-Encoding: UTF-8, identity User-Agent: 'User-Agent', 'Mozilla/5.0 %7B+%22q%22%3A+%22L%C3%83%C2%A4nge+8%2C5+cm%22%2C%22source%22%3A+%22de%22%2C+%22target%22%3A+%22en%22%2C+%22api_key%22%3A+%22%22%7D Indy ohne hoForceEncodeParams
Code:
ICS:
POST /translate HTTP/1.0
Connection: keep-alive Content-Encoding: UTF-8 Content-Type: application/json Content-Length: 105 Host: translate.lan:5000 Accept: application/json Accept-Charset: UTF-8 Accept-Encoding: UTF-8, identity User-Agent: 'User-Agent', 'Mozilla/5.0 { "q": "L??nge 8,5 cm","source": "de", "target": "en", "api_key": "##########"}
Code:
POST /translate HTTP/1.0
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */* Content-Type: application/json User-Agent: Mozilla/4.0 Host: translate.lan:5000 Content-Length: 107 { "q": "Länge 8,5 cm","source": "de", "target": "en", "api_key": "############"} |
AW: Indy HTTPClient Post umlaute
Ja ich weiss. Libre ist nicht so frei im Denken. Aber meinen Code hast du probiert? Sollte mit dem aktuellen libretranslate klappen. Und mit Indy TStrings geht's ja vielleicht auch nach Setzen von Eigenschaft X und Abschalten von Y und Löschen von Z ;-).
|
AW: Indy HTTPClient Post umlaute
Zitat:
das habe ich schon alles hinter mir. |
AW: Indy HTTPClient Post umlaute
Nun habe ich doch kurz libretranslate in einer meiner Linux-VMs installiert. Es stimmt, die Variante mit TStrings funktioniert nicht so wie erwartet. Das bekommt man zwar hin, aber einfacher ist es so:
Delphi-Quellcode:
Das funktioniert unter Delphi 2007 und z.B. Delphi 11 analog. Genauso klappt es auch mit ICS. Manuell in den Stream schreiben ist auch dort nicht notwendig.
function Translate(const AText, ASourceLang, ADestLang, AApiKey: string): string;
var Http: TIdHTTP; Data: TStream; begin Http := TIdHTTP.Create(nil); try Data := TStringStream.Create(UTF8Encode( Format('{"q": "%s","source": "%s", "target": "%s", "api_key": "%s"}', [AText, ASourceLang, ADestLang, AApiKey]))); try Http.Request.ContentType := 'application/json'; Result := UTF8Decode(Http.Post('http://192.168.119.53:5000/translate', Data)); finally Data.Free; end; finally Http.Free; end; end; ShowMessage(Translate('Länge 8,5 cm', 'de', 'en', '')); ShowMessage(Translate('Length 8,5 cm', 'en', 'de', '')); Wenn du Streams verwendest, funktioniert es mit Indy und ICS identisch. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 22:21 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