从C#中的URI字符串获取文件名


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

Answers:


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:在这种情况下,应在Uri.LocalPath的结果上使用Path.GetFileName。这是一种完全安全,经过严格检查的处理方式。我将编辑答案以包括此内容。请参阅:msdn.microsoft.com/en-us/library/...
里德科普塞

49
isFile似乎只看方案。因此:“ www / myFile.jpg ”返回false,“ file://www/something.jpg”返回true,因此在这种情况下它是无用的。
dethSwatch 2011年

6
还要提防查询字符串。http://www.test.com/file1.txt?a=b将导致file1.txt?a=b
朱利安

75

Uri.IsFile不适用于http网址。它仅适用于“ file://”。来自MSDN:“ 当Scheme属性等于UriSchemeFile时,IsFile属性为true。” 因此,您不能依赖它。

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

Uri.LocalPath进行Windows特定的转换,并且在非Windows环境中无法正常工作。请参阅以下我的答案以获取可移植的方法。
Kostub Deshmukh

虽然您不能使用它Uri.IsFile来测试http URL /方案,但是可以使用System.IO.Path.GetFileName(url);
Alex Pandrea

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

对于http网址,可接受的答案是有问题的。此外Uri.LocalPath,还会进行Windows特定的转换,并且有人指出将查询字符串留在那里。更好的方法是使用Uri.AbsolutePath

对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
Jeff Moser

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
在所有平台上的路径中,冒号都是不可接受的,因此,这种破解可能会失败,例如在* nix变体上运行的Mono.NET。最好使用System.Uri,因为它专门用于执行OP所需的操作。
richardtallent

1
有道理!我总是忘了Mono。我想到的是空格之类的东西,而不是冒号。
Mike Hofer,2009年

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);
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.