Ottieni il nome del file dalla stringa URI in C #


206

Ho questo metodo per afferrare il nome del file da un URI stringa. Cosa posso fare per renderlo più robusto?

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

Risposte:


388

Puoi semplicemente creare un oggetto System.Uri e utilizzare IsFile per verificare che sia un file, quindi Uri.LocalPath per estrarre il nome 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 file completo, utilizzare:

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

Questo fa tutto il controllo degli errori per te ed è neutrale dalla piattaforma. Tutti i casi speciali vengono gestiti per te in modo rapido e semplice.


Sono d'accordo, dovresti davvero usare la classe Uri perché fa già queste cose per te. +1
Doctor Jones,

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

2
@paulwhit: in tal caso, è necessario utilizzare Path.GetFileName sui risultati di Uri.LocalPath. Questo è un modo completamente sicuro e altamente controllato di gestirlo. Modificherò la mia risposta per includerla. Vedi: msdn.microsoft.com/en-us/library/…
Reed Copsey,

49
isFile sembra guardare solo lo schema. Quindi: " www / myFile.jpg " restituisce false, "file: //www/something.jpg" restituisce true, quindi in questo caso è inutile.
dethSwatch

6
Attenzione anche a una stringa di querystring. http://www.test.com/file1.txt?a=bsi tradurrà infile1.txt?a=b
Julian

76

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

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

Uri.LocalPath esegue conversioni specifiche di Windows e non funziona correttamente in un ambiente non Windows. Vedi la mia risposta di seguito per un modo portatile per farlo.
Kostub Deshmukh,

Sebbene non sia possibile utilizzare Uri.IsFileper eseguire il test su un URL / schema http, è possibile estrarre correttamente il nome del file da un URL http utilizzandoSystem.IO.Path.GetFileName(url);
Alex Pandrea

50

La maggior parte delle altre risposte sono incomplete o non trattano cose che seguono il percorso (query stringa / 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);
}

Risultati del test:

GetFileNameFromUrl("");                                         // ""
GetFileNameFromUrl("test");                                     // "test"
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/");              // ""

7
Perché dovrebbe GetFileNameFromUrl("test")risultare "test.xml" O è solo un errore di battitura?
ckittel,

27

La risposta accettata è problematica per gli URL http. Inoltre Uri.LocalPathesegue conversioni specifiche di Windows e come qualcuno ha sottolineato lascia stringhe di query. Un modo migliore è usareUri.AbsolutePath

Il modo corretto di farlo per gli URL http è:

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

7
Nota che per gli URL con escape come http://example.com/dir/hello%20world.txtquesto tornerebbe hello%20world.txtmentre l' Uri.LocalPathapproccio ritornerebbehello world.txt
Jeff Moser il

22

Penso che questo farà ciò di cui hai bisogno:

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

2
Sembra davvero una soluzione elegante, ma tieni presente che funziona solo su URI assoluti e restituisce un valore codificato / con escape (usa Uri.UnescapeDataString()per cambiare% 20 e + negli spazi).
Ronald

8
using System.IO;

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

Questo presuppone, ovviamente, 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 due punti non sono accettabili nei percorsi su tutte le piattaforme, quindi questo tipo di hack potrebbe non funzionare su, diciamo, Mono.NET in esecuzione su una variante * nix. Meglio usare System.Uri poiché è specificamente progettato per fare ciò di cui ha bisogno l'OP.
richardtallent,

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

2

questo è il mio esempio che puoi usare:

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

0

Semplice e diretto:

            Uri uri = new Uri(documentAttachment.DocumentAttachment.PreSignedUrl);
            fileName = Path.GetFileName(uri.LocalPath);
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.