2009-07-09 34 views
160

Tengo este método para obtener el nombre de archivo de un URI de cadena. ¿Qué puedo hacer para que sea más robusto?Obtener el nombre de archivo de la cadena de URI en 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; 
} 

Respuesta

321

puede simplemente hacer un objeto System.Uri, y utilizar ISFILE para verificar que es un archivo y, a continuación Uri.LocalPath para extraer el nombre del archivo.

Esto es mucho más seguro, ya que también proporciona un medio para verificar la validez del URI.


Editar en respuesta al comentario:

Para obtener sólo el nombre de archivo completo, que haría uso:

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

Esto tiene que ver todo de la comprobación de errores para usted, y es plataforma- neutral. Todos los casos especiales se manejan de manera rápida y fácil.

+0

Estoy de acuerdo, realmente deberías usar la clase Uri ya que hace estas cosas por ti. +1 –

+0

Sí, por más simple que parezca hacerlo usted mismo, la clase Uri tiene muchos elementos preincorporados de análisis/validación/codificación para usted. – STW

+2

Correcto, pero solo necesito el nombre del archivo, no la ruta completa del archivo. ¿Todavía no me dejan hacer ese paso en Uri.LocalPath? – paulwhit

7
using System.IO; 

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

Esto asume, por supuesto, que ha analizado el nombre del archivo.

editar # 2:

using System.IO; 

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

Esto debe manejar espacios y similares, en el nombre del archivo.

+3

Los puntos no son aceptables en las rutas en todas las plataformas, por lo que este tipo de hack podría fallar, por ejemplo, Mono.NET ejecutándose en una variante * nix. Es mejor usar System.Uri ya que está diseñado específicamente para hacer lo que el OP necesita. – richardtallent

+1

¡Un punto válido! Siempre me olvido de Mono. Pensé en espacios y cosas por el estilo, pero no en los dos puntos. –

51

Uri.IsFile no funciona con http urls. Solo funciona para "file: //". De MSDN: "La propiedad IsFile es true cuando la propiedad Scheme es igual a UriSchemeFile." Así que no puedes depender de eso.

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

Uri.LocalPath realiza conversiones específicas de Windows y no funciona correctamente en un entorno que no sea de Windows. Vea mi respuesta a continuación para una forma portátil de hacer esto. –

+0

Esto funciona. Gracias – mjb

19

La respuesta aceptada es problemática para http urls. Además, Uri.LocalPath realiza conversiones específicas de Windows, y como alguien señaló deja cadenas de consulta allí. Una mejor manera es utilizar Uri.AbsolutePath

La forma correcta de hacer esto para las direcciones URL HTTP es:

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

Tenga en cuenta que para URLs escapadas como 'http: // example.com/dir/hello% 20world.txt' esto devolvería' hello% 20world.txt' mientras que el enfoque 'Uri.LocalPath' devolvería' hello world.txt ' –

23

mayoría de las respuestas son incompletas o no se ocupan de las cosas que viene después de la ruta (cadena de consulta/hachís)

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

Resultados del ensayo:

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

Creo que esto va a hacer lo que necesita:

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

esta es mi muestra que puede utilizar:

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

uso:

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