2009-07-09 24 views
160

Ich habe diese Methode zum Abrufen des Dateinamens aus einem Zeichenfolge-URI. Was kann ich tun, um es robuster zu machen?Abrufen des Dateinamens aus der URI-Zeichenfolge in C#

private string GetFileName(string hrefLink) 
{ 
    string[] parts = hrefLink.Split('/'); 
    string fileName = ""; 

    if (parts.Length > 0) 
     fileName = parts[parts.Length - 1]; 
    else 
     fileName = hrefLink; 

    return fileName; 
} 

Antwort

321

Sie können nur ein System.Uri Objekt machen, und verwenden Sie IsFile es ist eine Datei, um zu überprüfen, dann Uri.LocalPath den Dateinamen zu extrahieren.

Dies ist viel sicherer, da Sie damit auch die Gültigkeit des URI überprüfen können.


bearbeiten als Antwort auf Kommentar:

nur den vollständigen Dateinamen zu erhalten, würde ich verwenden:

Uri uri = new Uri(hreflink); 
if (uri.IsFile) { 
    string filename = System.IO.Path.GetFileName(uri.LocalPath); 
} 

Dies bedeutet all den Fehler für Sie überprüft, und ist plattform- neutral. Alle Sonderfälle werden schnell und einfach für Sie erledigt.

+0

Ich stimme zu, Sie sollten wirklich die Uri-Klasse verwenden, da sie das Zeug für Sie bereits tut. +1 –

+0

Yup, so einfach wie es scheinen mag, die Uri-Klasse zu rollen, hat viele vorgerollte Parsing/Validierungs-/Kodierungs-Extras für Sie. – STW

+2

Richtig, aber ich brauche nur den Dateinamen, nicht den vollständigen Dateipfad. Muss ich diesen Schritt auf dem Uri.LocalPath noch machen? – paulwhit

7
using System.IO; 

private String GetFileName(String hrefLink) 
{ 
    return Path.GetFileName(hrefLink.Replace("/", "\\")); 
} 

THis setzt natürlich voraus, dass Sie die Dateinamen analysiert geführt haben.

EDIT # 2:

using System.IO; 

private String GetFileName(String hrefLink) 
{ 
    return Path.GetFileName(Uri.UnescapeDataString(hrefLink).Replace("/", "\\")); 
} 

Dies sollte behandeln Räume und dergleichen in den Dateinamen.

+3

Kolonnen sind in Pfaden auf allen Plattformen nicht akzeptabel, daher kann diese Art von Hack beispielsweise bei Mono.NET, das auf einer * nix-Variante läuft, fehlschlagen. Es ist besser, System.Uri zu verwenden, da es speziell dafür entwickelt wurde, das zu tun, was das OP benötigt. – richardtallent

+1

Ein gültiger Punkt! Ich vergesse Mono immer. Ich dachte an Räume und dergleichen, aber nicht an die Doppelpunkte. –

51

Uri.IsFile funktioniert nicht mit http URLs. Es funktioniert nur für "file: //". Von MSDN: "Die IsFile-Eigenschaft ist True, wenn die Scheme-Eigenschaft gleich UriSchemeFile ist." Sie können sich also nicht darauf verlassen.

Uri uri = new Uri(hreflink); 
string filename = System.IO.Path.GetFileName(uri.LocalPath); 
+0

Uri.LocalPath führt Windows-spezifische Konvertierungen durch und funktioniert in einer Nicht-Windows-Umgebung nicht ordnungsgemäß. Siehe meine Antwort unten für eine tragbare Möglichkeit, dies zu tun. –

+0

Das funktioniert. Danke – mjb

19

Die akzeptierte Antwort ist problematisch für HTTP-URLs. Darüber hinaus macht Uri.LocalPath Windows-spezifische Konvertierungen, und wenn jemand darauf hingewiesen wird, hinterlässt es dort Query-Strings. Ein besserer Weg ist Uri.AbsolutePath

Der richtige Weg, um dies zu tun für http-URLs ist:

Uri uri = new Uri(hreflink); 
string filename = System.IO.Path.GetFileName(uri.AbsolutePath); 
+0

Beachten Sie, dass für maskierte URLs wie "http: // beispiel.com/dir/hallo% 20world.txt" dies 'hallo% 20world.txt' zurückliefern würde, während der' Uri.LocalPath' Ansatz "Hallo Welt.txt" zurückgeben würde ' –

23

meisten Antworten entweder unvollständig sind oder sich nicht mit Sachen nach dem Pfad (Query-String/hash kommen).

readonly static Uri SomeBaseUri = new Uri("http://canbeanything"); 

static string GetFileNameFromUrl(string url) 
{ 
    Uri uri; 
    if (!Uri.TryCreate(url, UriKind.Absolute, out uri)) 
     uri = new Uri(SomeBaseUri, url); 

    return Path.GetFileName(uri.LocalPath); 
} 

Testergebnisse:

GetFileNameFromUrl("");           // "" 
GetFileNameFromUrl("test");          // "test.xml" 
GetFileNameFromUrl("test.xml");         // "test.xml" 
GetFileNameFromUrl("/test.xml");        // "test.xml" 
GetFileNameFromUrl("/test.xml?q=1");       // "test.xml" 
GetFileNameFromUrl("/test.xml?q=1&x=3");      // "test.xml" 
GetFileNameFromUrl("test.xml?q=1&x=3");       // "test.xml" 
GetFileNameFromUrl("http://www.a.com/test.xml?q=1&x=3");  // "test.xml" 
GetFileNameFromUrl("http://www.a.com/test.xml?q=1&x=3#aidjsf"); // "test.xml" 
GetFileNameFromUrl("http://www.a.com/a/b/c/d");     // "d" 
GetFileNameFromUrl("http://www.a.com/a/b/c/d/e/");    // "" 
8

ich das denke, das tun, was Sie brauchen:

var uri = new Uri(hreflink); 
var filename = uri.Segments.Last(); 
0

dies meine Probe ist, können Sie verwenden:

 public static string GetFileNameValidChar(string fileName) 
    { 
     foreach (var item in System.IO.Path.GetInvalidFileNameChars()) 
     { 
      fileName = fileName.Replace(item.ToString(), ""); 
     } 
     return fileName; 
    } 

    public static string GetFileNameFromUrl(string url) 
    { 
     string fileName = ""; 
     if (Uri.TryCreate(url, UriKind.Absolute, out Uri uri)) 
     { 
      fileName = GetFileNameValidChar(Path.GetFileName(uri.AbsolutePath)); 
     } 
     string ext = ""; 
     if (!string.IsNullOrEmpty(fileName)) 
     { 
      ext = Path.GetExtension(fileName); 
      if (string.IsNullOrEmpty(ext)) 
       ext = ".html"; 
      else 
       ext = ""; 
      return GetFileNameValidChar(fileName + ext); 

     } 

     fileName = Path.GetFileName(url); 
     if (string.IsNullOrEmpty(fileName)) 
     { 
      fileName = "noName"; 
     } 
     ext = Path.GetExtension(fileName); 
     if (string.IsNullOrEmpty(ext)) 
      ext = ".html"; 
     else 
      ext = ""; 
     fileName = fileName + ext; 
     if (!fileName.StartsWith("?")) 
      fileName = fileName.Split('?').FirstOrDefault(); 
     fileName = fileName.Split('&').LastOrDefault().Split('=').LastOrDefault(); 
     return GetFileNameValidChar(fileName); 
    } 

Verbrauch:

var fileName = GetFileNameFromUrl("http://cdn.p30download.com/?b=p30dl-software&f=Mozilla.Firefox.v58.0.x86_p30download.com.zip"); 
Verwandte Themen