Отримати ім’я файлу з рядка URI в C #


206

У мене є цей метод захоплення імені файлу з URI рядка. Що я можу зробити, щоб зробити його більш надійним?

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

Відповіді:


388

Ви можете просто зробити об’єкт System.Uri і використовувати IsFile для перевірки файлу, а потім Uri.LocalPath для вилучення імені файлу.

Це набагато безпечніше, оскільки це дає вам можливість перевірити дійсність URI.


Редагувати у відповідь на коментар:

Щоб отримати лише повне ім’я файлу, я б використав:

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

Це робить усі перевірки помилок для вас і є нейтральними для платформи. Усі спеціальні справи для вас швидко і легко.


Я погоджуюся, вам слід справді користуватися класом Uri, оскільки він вже робить це для вас. +1
Доктор Джонс

2
Правильно, але мені просто потрібно ім'я файлу, а не повний шлях до файлу. Хіба мені ще не залишається зробити цей крок на Uri.LocalPath?
paulwhit

2
@paulwhit: У такому випадку слід використовувати Path.GetFileName за результатами Uri.LocalPath. Це абсолютно безпечний, високо перевірений спосіб поводження з ним. Я відредагую свою відповідь, щоб включити цю. Дивіться: msdn.microsoft.com/en-us/library/…
Reed

49
isFile, здається, дивиться лише на схему. Отже: " www / myFile.jpg " повертає помилку, "файл: //www/something.jpg" повертає істину, тому в даному випадку це марно.
dethSwatch

6
Також остерігайтеся рядка запитів. http://www.test.com/file1.txt?a=bпризведе доfile1.txt?a=b
Джуліана

76

Uri.IsFile не працює з http-адресами. Він працює лише для "file: //". Від MSDN : "Властивість IsFile істинна, коли властивість Scheme дорівнює UriSchemeFile." Тож ви не можете від цього залежати.

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

Uri.LocalPath робить певні конверсії для Windows і не працює належним чином у середовищі, що не стосується Windows. Дивіться мою відповідь нижче про портативний спосіб зробити це.
Костуб Дешмух

Хоча ви не можете використовувати Uri.IsFileдля тестування http / схему http, ви можете успішно System.IO.Path.GetFileName(url);
дістати

50

Більшість інших відповідей або неповні, або не стосуються матеріалів, що надходять після шляху (рядок запиту / хеш).

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

Результати тесту:

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
Чому це GetFileNameFromUrl("test")призведе до того "test.xml" , що це просто помилка друку?
ckittel

27

Прийнята відповідь проблематична для URL-адрес http. Більше того, Uri.LocalPathвідбувається перетворення конкретних Windows, і, як хтось вказав, залишає рядки запитів. Кращий спосіб - використовуватиUri.AbsolutePath

Правильний спосіб зробити це для URL-адрес http:

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

7
Зауважте, що для уникнутих таких URL-адрес http://example.com/dir/hello%20world.txtповернеться, hello%20world.txtтоді як Uri.LocalPathпідхід повернетьсяhello world.txt
Джефф Мозер

22

Я думаю, що це зробить те, що потрібно:

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

2
Це справді виглядає як елегантне рішення, але пам’ятайте, що це працює лише на абсолютних URI та повертає закодоване / уникнене значення (використовуйте Uri.UnescapeDataString()для зміни% 20 та + на пробіли).
Рональд

8
using System.IO;

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

Це, звичайно, передбачає, що ви розібрали ім'я файлу.

ЗРІД №2:

using System.IO;

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

Це має обробляти пробіли тощо в імені файлу.


3
Колони неприйнятні для доріжок на всіх платформах, тому такий вид зламу може не працювати, скажімо, на Mono.NET, що працює на * nix варіанті. Краще використовувати System.Uri, оскільки він спеціально розроблений для того, щоб робити те, що потрібно ОП.
richardtallent

1
Дійсний бал! Я завжди забуваю про Моно. Я думав про простори тощо, але не про колони.
Майк Хофер

2

це мій зразок, який ви можете використовувати:

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

Використання:

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

0

Простий і прямий вперед:

            Uri uri = new Uri(documentAttachment.DocumentAttachment.PreSignedUrl);
            fileName = Path.GetFileName(uri.LocalPath);
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.