![]() |
UrlToFilename, brauche etwas Hilfe
Hi, ich habe eine Funktion gebastelt die mir aus einer URL-Link-Adresse einen Dateinamen geben soll.
Mit normalen Web-Links klappt das alles soweit so gut. Wenn nur eine Domäne in URL steht, das hätte ich gerne zu "index.html" abgeändert, habt ihr eine Idee wie ich das lösen kann? Hier der jetzige Code:
Delphi-Quellcode:
Vielleicht habt ihr ja auch noch Vorschläge was für Zeichen nicht in einen Dateinamen gehören?
Function UrlToFilename ( Const sURL: String ) : String;
var tmp: String; Cancel: Boolean; i: Integer; begin tmp := ''; Result := ''; i := Length(sURL); Cancel := False; repeat // strip input string down to last part after "/" if (sURL[i] <> '/') then tmp := sURL[i]+tmp else Cancel := True; Dec(i); until (Cancel = True) or ( i <= 0); if tmp = '' then tmp := 'index.html'; // default name for i := 1 to Length(tmp) do // filter out some bad chars begin if ((Ord(Char(tmp[i])) >= $20)and(Ord(Char(tmp[i])) <= $7F)) then // only use chars between ascii #32 and #127 if ((tmp[i]<>'"')and(tmp[i]<>'$')and(tmp[i]<>'*')and(tmp[i]<>'<')and(tmp[i]<>'>')and(tmp[i]<>'/')and(tmp[i]<>'\')) then // filter out bad filename chars Result := Result + tmp[i]; end; end; |
AW: UrlToFilename, brauche etwas Hilfe
Sowas mach' ich eigentlich immer auf die einfache und blöde Art:
Zuerst aus http:// bzw. https:// einen Laufwerksbuchstaben machen, also z. B. c:\. Danach alle / umdrehen zu \. Anschließend funktionieren ExtractFilename, ChangeFileExt ... wie bei "normalen" Dateinamen. Hat man 'ne Url mit Parametern, muss man vorher alles hinter dem ? wegwerfen.
Delphi-Quellcode:
Wenn man die Parameter auch noch auswerten muss, dann kann man z. B. aus ?, &, = und % jeweils 'nen \ machen, damit hat man dann eine "ellenlange" Pfadangabe.
Function UrlToFilename(Const sURL: String) : String;
var iPos: Integer; begin iPos := Pos('?',sUrl); if iPos > 0 then sUrl := Copy(sUrl,1,iPos - 1); iPos := Pos('//',sUrl); if iPos > 0 then sUrl := 'c:' + Copy(sUrl,iPos + 1,Length(sUrl)); sUrl := AnsiReplaceText(sUrl,'/','\'); Result := ExtractFileName(sUrl); end; procedure Irgendwas; begin // Hier sollte nun newreply.php ausgeben werden: ShowMessage(UrlToFilename('https://www.delphipraxis.net/newreply.php?do=postreply&t=196264#039;)); end; Hier muss man dann ggfls. schauen, was im Einzelfall sinnvoll weiterzuverwenden ist. |
AW: UrlToFilename, brauche etwas Hilfe
Welche Unit soll ich nehmen um AnsiReplaceText() bereitzustellen, System.AnsiStrings oder System.StrUtils?
Delphi-Quellcode:
Das funktioniert astrein aber das Hauptproblem bleibt bestehen,
Function UrlToFilename(sURL: String) : String; // da Du auf sURL schreibst hab ich Const entfernt
var iPos: Integer; begin iPos := Pos('?',sUrl); if iPos > 0 then sUrl := Copy(sUrl,1,iPos - 1); iPos := Pos('//',sUrl); if iPos > 0 then sUrl := 'c:' + Copy(sUrl,iPos + 1,Length(sUrl)); sUrl := AnsiReplaceText(sUrl,'/','\'); Result := ExtractFileName(sUrl); if Result = '' then Result := 'index.html'; // und das hier zugefügt end; hier ein Beispiel
Delphi-Quellcode:
da wünsche ich mir als Ergebnis ein "index.html"
ShowMessage(UrlToFilename('https://www.delphipraxis.net/');
oder ShowMessage(UrlToFilename('https://www.delphipraxis.net'); |
AW: UrlToFilename, brauche etwas Hilfe
Das Ergebnis soll also etwas sein, was nicht da ist?
Also http:// bzw. https.// wegwerfen. Dann schauen, ob es im Rest einen / gibt. Wenn nein ist das Ergebnis index.html. Gibt es einen / dann alles davor wegwerfen. Bleibt nur der / über, dann ist das Ergebnis ebenfalls index.html. Gibt es den / plus nochirgendwas, ist alles ab dem / Pfad und Dateiname. Ist darin noch ein ? enthalten, dann alles vor dem ? nehmen. Evntuell vorhandene / umdrehen zum \. |
AW: UrlToFilename, brauche etwas Hilfe
Keine Lösung, aber vielleicht paar Anregungen
Delphi-Quellcode:
var
s: string; p: Integer; begin s := 'https://www.delphipraxis.net/196264-urltofilename-brauche-etwas-hilfe.html#post1401364'; p := LastDelimiter('/', s); s := Copy(s, p + 1, MaxInt); p := Pos('#', s); if p > 0 then Delete(s, p, MaxInt); if not(AnsiEndsText('.html', s) or AnsiEndsText('.htm', s) or AnsiEndsText('.php', s)) then ShowMessage(Format('"%s" scheint keine Datei zu sein', [s])) else ShowMessage(s); end; |
AW: UrlToFilename, brauche etwas Hilfe
Vielen Dank für Tipps!
Delphi-Quellcode:
So macht es genau was ich will, tut mir leid das ich den Source so verunstaltet habe aber so scheint es zu funktionieren.
Function UrlToFilename( Const sURL: String ) : String;
var tmp: String; iPos: Integer; begin Result := ''; tmp := sURL; iPos := Pos('?',tmp); if iPos > 0 then tmp := Copy(tmp,1,iPos - 1); iPos := Pos('//',tmp); if iPos > 0 then begin tmp := Copy(tmp,iPos+2,Length(tmp)); iPos := Pos('/',tmp); if iPos <> 0 then repeat tmp := Copy(tmp,iPos + 1,Length(tmp)); iPos := Pos('/',tmp); until iPos = 0 else tmp := 'index.html'; for iPos := 1 to Length(tmp) do begin if ((Ord(Char(tmp[iPos])) >= $20)and(Ord(Char(tmp[iPos])) <= $7F)) then // only use chars between ascii #32 and #127 if ((tmp[iPos]<>'"')and(tmp[iPos]<>'$')and(tmp[iPos]<>'?')and(tmp[iPos]<>'*')and(tmp[iPos]<>'<')and(tmp[iPos]<>'>')and(tmp[iPos]<>'/')and(tmp[iPos]<>'\')) then // filter out bad filename chars Result := Result + tmp[iPos]; end; end; if Result = '' then Result := 'index.html'; end; @Delphi.Narium: Ja, so grausam es klingen mag aber was Du schreibst trifft den Nagel auf den Kopf. Zuerst alles hinter "?" kappen Dann alles vor "//" kappen Jetzt gucken ob ein "/" existiert oder "index.html" ausgeben. Falls mehrere "/" existieren halt nur den Rest dahinter verwenden. Wenn dann noch etwas übrig sein sollte durch den Char-Checker jagen. Zu guter letzt, falls kein Ergebnis vorliegt ein "index.html" draus machen. |
AW: UrlToFilename, brauche etwas Hilfe
Jag die URL doch erst durch
![]() |
AW: UrlToFilename, brauche etwas Hilfe
Zitat:
Lese doch erst mal um was es ihm geht. Dann gebe dein Kommentar ab. Er will keine riesen Komponenten verwenden sondern alles klein halten was will er also mit dieser RIESEN Classe? Zudem täte es ein einfaches Split auch. gruss |
AW: UrlToFilename, brauche etwas Hilfe
Delphi-Quellcode:
Das tuts auch, hat zumindest erste alpha phase überstanden :P
type
TRealURL = record OriginalURL, {whatever input it was - its stored here} Protocol, {holds used protocol without "://", example "http"} Username, {Ham} Password, {Eggs} Domain, {can be www or ip-adress} Sublevel, {may just hold char "/" if source is root plus a filename} Filename, {holds logical Name from given input} Parameter, {if you need them for further usage} Port: String; {Port Royale} end; // TRealURL Function ExpandURL ( Const sURL: String ) : TRealURL; var tmp, NoParam: String; i, ii: Integer; begin Result.OriginalURL := sURL; Result.Protocol := ''; Result.Username := ''; Result.Password := ''; Result.Domain := ''; Result.Sublevel := ''; Result.Filename := ''; Result.Parameter := ''; Result.Port := ''; (* Get Parameter & Port *) tmp := sURL; NoParam := ''; if Pos('?', tmp) > 0 then begin tmp := Copy(tmp, Pos('?', tmp), Length(tmp)); if Pos(':',tmp) > 0 then Result.Parameter := Copy(tmp, 1, Pos(':',tmp)-1) else Result.Parameter := tmp; if Pos(':',tmp) > 0 then Result.Port := Copy(tmp, Pos(':', tmp)+1, Length(tmp)); NoParam := Copy(sURL, 1, Pos('?', sURL)-1); end else NoParam := tmp; (* Get Protocol *) tmp := NoParam; if Pos('://',tmp) > 0 then Result.Protocol := Copy(tmp, 1, Pos('://',tmp)-1); (* Get Username *) if Pos('@', tmp) > 0 then begin i := Length(Result.Protocol); if Length(Result.Protocol) > 0 then Inc(i,3); Inc(i); tmp := Copy(NoParam, i, Length(NoParam)); if Pos(':',tmp) > 0 then tmp := Copy(tmp, 1, Pos(':',tmp)-1); if Pos('@',tmp) > 0 then tmp := Copy(tmp, 1, Pos('@',tmp)-1); Result.Username := tmp; end; (* Get Password *) tmp := NoParam; if ((Pos('@', tmp) > 0)and(Pos(':', tmp) > 0)) then begin i := Length(Result.Protocol)+Length(Result.Username); if Length(Result.Protocol) > 0 then Inc(i,3); if Length(Result.Username) > 0 then Inc(i); Inc(i); tmp := Copy(NoParam, i, Length(NoParam)); tmp := Copy(tmp, 1, Pos('@',tmp)-1); Result.Password := tmp; end; (* Get Domain & Port *) begin i := Length(Result.Protocol)+Length(Result.Username)+Length(Result.Password); if Length(Result.Protocol) > 0 then Inc(i,3); if Length(Result.Username) > 0 then Inc(i); if Length(Result.Password) > 0 then Inc(i); Inc(i); tmp := Copy(NoParam, i, Length(NoParam)); if Pos('/', tmp) > 0 then tmp := Copy(tmp, 1, Pos('/', tmp)-1); if Pos(':', tmp) > 0 then begin Result.Port := Copy(tmp, Pos(':', tmp)+1, Length(tmp)); tmp := Copy(tmp, 1, Pos(':', tmp)-1); end; Result.Domain := tmp; end; (* Get Sublevel & Port *) begin i := Length(Result.Protocol)+Length(Result.Username)+Length(Result.Password)+Length(Result.Domain); if Length(Result.Protocol) > 0 then Inc(i,3); if Length(Result.Username) > 0 then Inc(i); if Length(Result.Password) > 0 then Inc(i); Inc(i); tmp := Copy(NoParam, i, Length(NoParam)); i := 0; for ii := 1 to Length(tmp) do if tmp[ii] = '/' then i := ii; if i > 0 then tmp := Copy(tmp, 1, i); if Pos(':', tmp) > 0 then begin Result.Port := Copy(tmp, Pos(':', tmp)+1, Length(tmp)); tmp := Copy(tmp, 1, Pos(':', tmp)-1); end; Result.Sublevel := tmp; end; (* Get Filename & Port *) begin i := Length(Result.Protocol)+Length(Result.Username)+Length(Result.Password)+Length(Result.Domain)+Length(Result.Sublevel); if Length(Result.Protocol) > 0 then Inc(i,3); if Length(Result.Username) > 0 then Inc(i); if Length(Result.Password) > 0 then Inc(i); Inc(i); tmp := Copy(NoParam, i, Length(NoParam)); if Pos(':', tmp) > 0 then begin Result.Port := Copy(tmp, Pos(':', tmp)+1, Length(tmp)); tmp := Copy(tmp, 1, Pos(':', tmp)-1); end; Result.Filename := tmp; end; end; Zitat:
Gruß zurück! |
AW: UrlToFilename, brauche etwas Hilfe
Zitat:
Ich hoffe du blickst da in 10 Jahren noch durch. gruss |
AW: UrlToFilename, brauche etwas Hilfe
Zitat:
Wenn Du Dich mit dem Aufbau einer URI bzw. URL befassen möchtest, ist das ein schönes Forschungsprojekt. Aber eben nicht mehr - und insbesondere auch keine implizite Empfehlung, das "mal eben selbst zu machen", denn das gibt es bereits. |
AW: UrlToFilename, brauche etwas Hilfe
Hallo, ich versuche so etwas wie einen Download Manager zu erstellen, die UrlToFilename funktion dient mir dabei in erster hinsicht ein online-überprüfen auszuweichen, um Dateinamen für eine Listbox zu aufzubereiten, bis hier hin ist noch nichts weiter mit dem Namen geschehen, dank des Records habe ich ja auch noch den Original-String.
An einen Online-Status abfragen Knopf habe ich auch schon gedacht, da kommt dann auch der Dateiname nochmal vor, für welche Methode ich mich da entscheide steht kaum noch zur Debatte, THttpClient hats mir voll angetan:thumb: |
AW: UrlToFilename, brauche etwas Hilfe
Zitat:
Aber das Interessiert hier keinen es ist ein Spass\Fan\Lern Projekt und letztendlich bei deiner Aussage bleibt der Lerneffekt auf der Strecke und der ist dann gleich 0. Es muss oder sollte nicht immer darum gehen eben schnell etwas zu machen oder fertigen Code zu verwenden.. Wie hast du denn früher einmal angefangen Copy/Paste ? Denke mal nicht denn da hättest du nichts bei gelernt. Ob das im Sinne des Betrachters liegt mag dahin gestellt sein. gruss |
AW: UrlToFilename, brauche etwas Hilfe
Emil, wenn Du die zweite Hälfte meines Beitrages gelesen und verstanden hättest, wüsstest Du, dass ich sehr wohl geschrieben habe, dass dies ein schönes Forschungsprojekt ist, um sich mit dem Thema „Aufbau einer URI“ zu beschäftigen.
|
AW: UrlToFilename, brauche etwas Hilfe
Zitat:
"%xx" durch Char($xx) ersetzen Und für ExtractFileName, ExtractFilePath usw. muß das http:// nicht durch einen Laufwerksbuchstaben ersetzt werden. Einige Funktionen kommen mit \ oder / zurecht, aber statt \ nimmt man besser ![]() Diese Funktionien kommen auch mit UNC-Pfaden zurecht, also ihnen ist der Anfang quasi egal. ABER, warum immer alles selber machen? In den Indy und ähnlichen Komponenten verstecken sich irgendwo Funktionen, um eine URL/URI in seine Teile zu zerlegen. ![]() mal bei ![]() ![]() oder im TIdURL (Indy), ![]() ... |
AW: UrlToFilename, brauche etwas Hilfe
Zitat:
Ich werfe mal folgendes URL-Formmat ins Rennen.
Code:
.de/index.php/?page=wasauchimmerfuereineseite?foo=bar
|
AW: UrlToFilename, brauche etwas Hilfe
Ja Danke nochmal, hab die Raute Zeichen bisher total ignoriert.
Hier nun mini Update zu meinem Code, auch auf ein "?" oder "#" direkt nach einem "/" reagiere ich nun.
Delphi-Quellcode:
Das hier zeigt mir mein Programm mit Deiner Url an:
(* Get Parameter & Port *)
tmp := sURL; NoParam := ''; i := Pos('?', tmp); if i = 0 then i := Pos('#', tmp); if i > 0 then begin if sURL[i] = '?' then if tmp[i-1] = '/' then tmp := Copy(tmp, i, Length(tmp)) else tmp := Copy(tmp, Pos('?', tmp), Length(tmp)) else if sURL[i] = '#' then if tmp[i-1] = '/' then tmp := Copy(tmp, i, Length(tmp)) else tmp := Copy(tmp, Pos('#', tmp), Length(tmp)); if Pos(':',tmp) > 0 then Result.Parameter := Copy(tmp, 1, Pos(':',tmp)-1) else Result.Parameter := tmp; if Pos(':',tmp) > 0 then Result.Port := Copy(tmp, Pos(':', tmp)+1, Length(tmp)); if sURL[i-1] = '/' then NoParam := Copy(sURL, 1, i-2) else NoParam := Copy(sURL, 1, i-1); end else NoParam := tmp;
Code:
Vielleicht lasse ich mir noch was einfallen das ich auch nach einem Punkt schaue so das der Sublevel zu "/" wird und Filename "index.php"
Original: .de/index.php/?page=wasauchimmerfuereineseite?foo=bar
Protocol: Username: Password: Domain: .de Sublevel: / Filename: index.php Parameter: ?page=wasauchimmerfuereineseite?foo=bar Port: Updated, Dateiname funktioniert nun mit der Url. |
AW: UrlToFilename, brauche etwas Hilfe
Zitat:
EDIT: Zitat:
Aber nicht praktisch vor allem wenn es um das debuggen geht. Wie willst du in dieser Zeile hinter then, else einen breakpoint setzen ?
Delphi-Quellcode:
if sURL[i] = '#' then if tmp[i-1] = '/' then tmp := Copy(tmp, i, Length(tmp)) else tmp := Copy(tmp, Pos('#', tmp), Length(tmp));
Fehlersuche ist dann irgendwie Glückssache. gruss |
AW: UrlToFilename, brauche etwas Hilfe
Zitat:
Mit sowas könnte ich mich ja anfreunden:
Code:
? steht vor dem ersten Parameter, die weiteren werden durch & getrennt, also einmal ?Name=Wert und alle weiteren dann mit &Name=Wert.
.de/index.php/?page=wasauchimmerfuereineseite&foo=bar
Die Raute weist bei HTML-Seiten normalerweise darauf hin, dass man innerhalb dieser Seite zu einer Sprungmarke navigieren möchte. Wer mal so richtig ins Eingemachte schauen will: ![]() |
AW: UrlToFilename, brauche etwas Hilfe
Zitat:
Ich mache es oft bei simplen Dingen so das eine Anweisung/Auswertung pro Zeile entsteht mit der ich in nächster Zeile weiterarbeite. Das ist für mich strukturierter aber man kann natürlich allem mehr Luft machen, dann hat man was fürs Auge :-D Fehlersuche während man nur String-Inhalt prüft und kopiert, da reicht mir auch das Ergebnis danach. Soweit ich das Beurteilen kann ist der Code Recht Stabil gegen Fehler aber falls Du Dich erniedrigen würdest um mein Code bei Dir auszuführen um etwaige Fehler zu entlarven, das wäre auch hilfreich. Ich hab dutzende Kombinationen aus real und fake inputs durchgetestet ohne selbst auf Fehler zu stoßen. (Selbst wenn es im Eigentlichen Einsatz von einer Online-Prüfung abgelöst wird solls im Vorfeld auch schon glänzen) Zitat:
![]() PS: Parameter bedeuted bei mir alles was nicht zum Rest gehört, ich werte das ja nicht aus sondern filter es nur raus. |
AW: UrlToFilename, brauche etwas Hilfe
Zitat:
Gegen alle Fehler kann man sich nicht absichern. Aber gegen solche minderschweren vielleicht noch. |
AW: UrlToFilename, brauche etwas Hilfe
Nein, sollte man nicht.
ein weiteres ? nach dem Fragezeichen, aber vor einem # ... das gehört zum Parameter ![]() protcol = http login = domain = xyz.de port = path = index.php/ param-name 1 = page param-value 1 = wasauchimmerfuereineseite?foo=bar param-name 2 = dsa param-value 2 = 456 ancor = pos Wenn jemand beim Zusammenbau der URL einen Fehler gemacht hat, dann hat er Pech, aber es währe grob fahrlässig, wenn man hier nun das zweite ? entgegen der Definition auch zum Trennen verwendet wird :!: Und die minimalste Kurzfassung des Standards hatte ich oben schon erwähnt. > Wenn man die einzelnen Werte/Parameter nicht auswerten will, ansonsten noch den vorher extrahierten Parameterstring an & auftrennen und dann nochmal jeweils an den ersten = in Name und Value. Zusätzllich gibt es dann noch die zwei Varianten der Codierung von Unicode und Sonderzeichen, jeweils bei Path/Params/Anker das mit dem % und bei Domain das ACE-Zeugs für IDN (Umlautdomains). Bei Username/Passwort weiß ich die Kodierung grade nicht. (entweder nur ASCII möglich der ich tendiere eher zum älteren %) Aber das braucht man zum Zerlegen nicht, sondern nur zum Unwandeln in eine lesbare Form, denn das ist gerade dafür da, dass die ersten Trenn-Regeln nicht konterminiert werden und weiterhin gelten, auch wenn entsprechende Zeichen in der URL vorkommen. |
AW: UrlToFilename, brauche etwas Hilfe
Zitat:
Klar würde ich nur ich verwende D2010 und alle uses jedes Mal umzuschreiben ist einfach nur nervig. gruss |
AW: UrlToFilename, brauche etwas Hilfe
@Emil: Teste mal bitte von
![]() Ich weiß nicht seid wann System.Net.URLClient existiert aber darum geht es ja nicht, einfach das TURI Zeug wegdenken und Memo1 betrachten, das geht mit jeder Delphi Version, höchstens Unit Namespace rausnehmen. Das wäre toll von Dir zu hören! |
AW: UrlToFilename, brauche etwas Hilfe
Zitat:
Vcl.Forms, Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.ExtCtrls; müsste also alles umschreiben. Ja nur die uses aber das ist mir schon genug. Aber habe es trotzdem geladen. Nun URLClient gibt es unter D2010 nicht also muss ich nicht weiter testen. gruss |
AW: UrlToFilename, brauche etwas Hilfe
Ja, das ist Neuer.
Die Funktionen des Indy gibt es aber, da Indy schon ein paar Jahre länger direkt mitgeliefert wird. |
AW: UrlToFilename, brauche etwas Hilfe
Zitat:
Entschuldige aber ich möchte kein Indy Installieren da ich Hauptsächlich mit der WinApi arbeite. Es müll't mir mein System zu. gruss |
AW: UrlToFilename, brauche etwas Hilfe
Es geht ja auch nur um Strings, keine extra units von nöten, ich kann auch ein Winapi beispiel basteln wenn das die Sache erleichtert.
|
AW: UrlToFilename, brauche etwas Hilfe
Zitat:
Es ist seit jahrzehnten im Delphi enthalten. |
AW: UrlToFilename, brauche etwas Hilfe
Zitat:
gruss |
Alle Zeitangaben in WEZ +1. Es ist jetzt 07:40 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