Entwickler-Ecke
Internet / Netzwerk - TIdFTP.Get Umlautproblem
Gerhard_S - Mo 22.10.12 00:22
Titel: TIdFTP.Get Umlautproblem
Wenn ich die Datei 'Märchenstunde.html' mit TIdFTP direkt herunterlade (IdFTP1.Get('Märchenstunde.html',...), funktioniert das problemlos. Wenn ich den Inhalt des DirectoryListings in eine Stringlist kopiere und dann die Stringlist auf der lokalen Festplatte speichere, zeigen mir Notepad und Notepad++ den korrekten Dateinamen an. Aber hier:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17:
| if AFTP.DirectoryListing.Count > 2 then for I := 0 to AFTP.DirectoryListing.Count -1 do begin if AFTP.DirectoryListing[i].ItemType = ditFile then begin if Fileexists(ALocalPath +AFTP.DirectoryListing[i].FileName) then begin if bOverwrite then begin DeleteFile(ALocalPath +AFTP.DirectoryListing[i].FileName); AFTP.Get(AFTP.DirectoryListing[i].FileName, ALocalPath +AFTP.DirectoryListing[i].FileName, true, true); end; end else AFTP.Get(AFTP.DirectoryListing[i].FileName, ALocalPath +AFTP.DirectoryListing[i].FileName, true, true); end; end; |
gibt es die Fehlermeldung 'No such file', wenn das Programm auf 'Märchenstunde.html' trifft. Auf der Platte landet dann eine Null-Byte-Datei mit einem Fragezeichen anstelle des 'ä'.
Kann man - außer der Umbenennung der Datei - was dagegen tun?
jaenicke - Mo 22.10.12 06:06
Welche Delphiversion? Welche Indyversion (hoffentlich die aktuelle)?
Hast du vielleicht ein kleines Demoprojekt, mit dem wir das ausprobieren können? (Wenn ich auf meinen Server so eine Datei lege und die Daten eingebe.)
baka0815 - Mo 22.10.12 15:30
Klingt nach einem Problem mit dem Zeichensatz. UTF-8 <> ANSI vielleicht?
Bzw. AnsiChar zu WideChar oder UTF8Char?
jaenicke - Mo 22.10.12 16:18
Ja, so etwas vermute ich auch. Genau deshalb habe ich nach einem Demoprojekt gefragt. Das dauert sonst nur unnötig lange die Möglichkeiten durchzugehen. ;-)
Gerhard_S - Mo 22.10.12 19:06
Hallo,
anbei das Demo-Projekt. Der Fehler tritt in Zeile 429 auf.
Danke im Voraus.
Tipps zum Testen:
1. Lege auf dem Webserver ein Verzeichnis ('test') an, das eine Datei mit Umlaut im Namen ('Märchen.html') und andere Dateien enthält.
2. Wähle im ListView die Datei mit Umlaut im Namen ('Märchen.html') aus und klicke auf Download. Das sollte funktionieren.
3. Stelle die Verbindung wieder her. Gehe im ListView eine Ebene nach oben, markiere das Verzeichnis 'test' und klicke auf Download. Der Download bricht ab, sobald er die Datei Märchen.html erreicht hat, mit der Meldung 'No such file'.
mandras - Di 23.10.12 14:17
Das war ja eine üble Nuß!
Also:
Ich habe auf meinem Server eine Datei namens märchen.html angelegt.
Wenn Dein Programm das Verzeichnis listet liefert der Server für das "ä" den Code 228 (ist das ä im Unicode).
Wenn Dein Programm dann aber die Datei empfangen will wird für das ä $C3 $A4 gesandt (das ist das ä in UTF8).
Um das abzustellen müßtest Du an geeigneter Stelle im Code einbauen:
Delphi-Quelltext
1:
| IdFTP1.IOHandler.DefStringEncoding :=TIdTextEncoding.ANSI; |
So klappte es dann bei mir.
Richtig verstehen tue ich das Problem aber nicht da laut Doku das Indy ja UTF8 verwendet falls der Server das beherrscht. Und meine schickt beim Connect daß er das kann..
Gerhard_S - Di 23.10.12 18:36
Hallo mandras,
besten Dank für deine Bemühungen.
Kannst du mir sagen, was du für eine "geeignete Stelle im Code" zum Einbau der Ansi-Codierung hältst?
Ich habe es versucht:
a) direkt vor dem Get-Befehl - Fehler bleibt
b) direkt vor dem letzten List-Befehl - Fehler bleibt
c) als ersten Befehl der for-Schleife zum Anstoßen des Downloads - Fehler bleibt.
mandras - Di 23.10.12 22:24
Ich habe es in Unit1, Zeile 324 eingefügt und nun nochmal unter W7 64 probiert.
Weitere Info: Ich nutze Delphi XE2, Indy 10.5.8
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7:
| if bOverwrite = true then begin DeleteFile(LocDir+'\'+SL[i]); IdFTP1.IOHandler.DefStringEncoding :=TIdTextEncoding.ANSI; IdFTP1.Get(SL[i], LocDir + '\' + (SL.Strings[i]), boverwrite, False); end |
Gerhard_S - Di 23.10.12 23:05
Schade, das ist die Stelle für das direkte Herunterladen von Dateien aus einem geöffneten Ordner (via Schleife über alle markierten Dateien). Das hat bei mir schon von Anfang an funktioniert. ("Wenn ich die Datei 'Märchenstunde.html' mit TIdFTP direkt herunterlade (IdFTP1.Get('Märchenstunde.html',...), funktioniert das problemlos.")
Was nicht funktioniert, ist das Herunterladen dieser Datei durch Abarbeitung eines DirectoryListing von einem Ordner, der nicht im ListView, sondern nur im Code per IdFTP1.ChangeDir(FolderName) geöffnet wird. Dieser Download erfolgt in der procedure DownloadFolder(....), ca. Zeile 393, Auszug daraus in meinem ersten Beitrag zum Thema mit Kommentar "hier Fehler".
Der Fehler liegt irgendwo hier:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10:
| if AFTP.DirectoryListing.Count > 2 then for i := 0 to AFTP.DirectoryListing.Count -1 do begin if AFTP.DirectoryListing[i].ItemType = ditFile then begin ShowMessage('1. AFTP.DirectoryListing[i].FileName: '+ AFTP.DirectoryListing[i].FileName);
.... |
mandras - Di 23.10.12 23:23
morgen.. :)
Lieben Gruß!
jaenicke - Mi 24.10.12 06:00
Wie sieht denn das falsche ä aus? Wenn es zwei Zeichen mit einem "komischen" großen A sind, hilft vielleicht Utf8ToString.
mandras - Mi 24.10.12 11:42
So, ich habe mir das ganze noch mal wachen Kopfes angesehen.
Ich weiß nun nicht, ob es Dir hilft, bei mir war es jedenfalls ein Zeichensatzproblem.
Vorab:
Ich habe auf meinem FTP-Server eine Datei namens "märchen.html" erzeugt, wobei definitiv der UTF8-Zeichensatz zum Einsatz kam.
Bei meinen bisherigen Postings arbeitete ich mit einer gleichnamigen Datei, die war aber im Unicode-Zeichensatz. Interessanterweise zeigte Filezilla diese Datei mit korrektem Namen an, konnte sie dann aber nicht herunterladen!
Nun zum IDFTP:
Die List-Methode erstellt die StringList so wie der Server sie liefert, also UTF8-Kodiert, wobei das "ä" als 2-Byte-Zeichen kommt.
Wird nun ein Download einer solchen Datei versucht erfolgt noch eine Zeichenumkodierung, aus den 2 Bytes für das "ä" werden 4. Deshalb klappte es wohl nicht.
Ich habe Dein Programm ein wenig überarbeitet, und zwar die Funktion
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20:
| procedure TForm1.FillLV(TheFTP: TIDFTP); var i: integer; ListItem: TListItem; var FLI: TIdFtpListItems; begin FLI := TheFTP.DirectoryListing; for i:=0 to FLI.Count-1 do begin ListItem:= ListView1.Items.Add; ListItem.Caption := FLI[i].FileName; case FLI[i].ItemType of ditDirectory : ListItem.SubItems.Add('dir'); ditFile : ListItem.SubItems.Add('file'); end; ListItem.SubItems.Add(IntToStr(FLI[i].Size)); ListItem.SubItems.Add(DateTimeToStr(FLI[i].ModifiedDate)); ListItem.SubItems.Add('unique'); ListItem.SubItems.Add(FLI[i].PermissionDisplay); end; end; |
und natürlich die Aufrufe dieser Funktion. Vollständiger Quelltext im Anhang.
Was hat sich geändert gegenüber Deinem Programm?
Die Ermittlung der Dateinamen und das Parsing wird über die IDFTP-Komponente selbst erledigt. Dabei werden die Zeichensätze auch korrekt behandelt.
Bei mir funktionert das Programm so korrekt, ich habe es nun nicht mit FTP-Servern getestet die kein UTF8 beherrschen.
Gerhard_S - Mi 24.10.12 18:45
Noch mal besten Dank für deine Bemühungen. Bei mir klappt's leider immer noch nicht.
Vielleicht liegt es an den Eigenschaften des Servers. Dazu werde ich einen neuen Thread aufmachen.
(Übrigens habe ich festgestellt, dass die von den Indies selbst erstellte Demo einen Download über den Umweg der Listbox macht, in die sie die Dateinamen hineinschreiben. Da in meinem Code die als Kopie des DirectoryListing erstellte Stringlist alles richtig anzeigt, bietet sich das als Workaround an.)
mandras - Mi 24.10.12 20:08
Schade.
Ich könnte höchstens anbieten daß Du einen entspr. FTP-Account für mich probehalber einrichtest mit einem Verzeichnis in welchem so eine böse Datei liegt. Dann könnte ich einmal nachsehen woran es evtl. liegt.
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2025 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!