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.