2009-07-09 27 views
160

Ho questo metodo per afferrare il nome del file da un URI di stringa. Cosa posso fare per renderlo più robusto?Ottieni il nome del file dalla stringa URI 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; 
} 

risposta

321

Si può solo fare un oggetto System.Uri, e utilizzare isfile per verificare che sia un file, quindi Uri.LocalPath per estrarre il nome del file.

Questo è molto più sicuro, in quanto fornisce un mezzo per verificare anche la validità dell'URI.


Modifica in risposta al commento:

per ottenere solo il nome del file completo, userei:

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

Questo fa tutto il controllo degli errori per voi, ed è dalla piattaforma neutro. Tutti i casi speciali vengono gestiti rapidamente e facilmente.

+0

Sono d'accordo, dovresti davvero usare la classe Uri come già fa questa roba per te. +1 –

+0

Sì, per quanto semplice possa sembrare il roll-your-own della classe Uri ci sono un sacco di pre-rollate di analisi/validazione/codifica. – STW

+2

Giusto, ma ho solo bisogno del nome del file, non del percorso completo del file. Non sono ancora lasciato per fare quel passo su Uri.LocalPath? – paulwhit

7
using System.IO; 

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

Questo presuppone, naturalmente, che tu abbia analizzato il nome del file.

EDIT # 2:

using System.IO; 

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

Questo dovrebbe gestire spazi e simili nel nome del file.

+3

I coloni non sono accettabili nei percorsi su tutte le piattaforme, quindi questo tipo di hack potrebbe fallire, ad esempio, su Mono.NET in esecuzione su una variante * nix. Meglio usare System.Uri poiché è progettato specificamente per fare ciò di cui l'OP ha bisogno. – richardtallent

+1

Un punto valido! Mi dimentico sempre di Mono. Ho pensato a spazi e simili, ma non ai due punti. –

51

Uri.IsFile non funziona con gli URL http. Funziona solo con "file: //". Da MSDN: "La proprietà IsFile è true quando la proprietà Scheme equivale a UriSchemeFile." Quindi non puoi dipendere da questo.

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

Uri.LocalPath esegue conversioni specifiche di Windows e non funziona correttamente in un ambiente non Windows. Vedere la mia risposta qui sotto per un modo portatile per farlo. –

+0

Questo funziona. Grazie – mjb

19

La risposta accettata è problematica per gli URL http. Inoltre, Uri.LocalPath esegue conversioni specifiche di Windows e, come indicato da qualcuno, lascia le stringhe di query. Un modo migliore è quello di utilizzare Uri.AbsolutePath

Il modo corretto di fare questo per URL HTTP è:

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

Nota che per gli URL con caratteri di escape come 'http: // example.com/dir/hello% 20world.txt' questo restituisce' ciao% 20world.txt' mentre l'approccio 'Uri.LocalPath' restituisce' ciao world.txt ' –

23

La maggior parte delle risposte sono o incomplete o non trattare con roba che dopo il percorso (query string/hash).

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); 
} 

I risultati dei test:

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

Penso che questo farà quello che vi serve:

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

questo è il mio campione è possibile utilizzare:

 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); 
    } 

Usage:

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