239

I have this method for grabbing the file name from a string URI. What can I do to make it more robust?

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;
}
paulwhit
  • 8,719
  • 4
  • 29
  • 30

10 Answers10

443

You can just make a System.Uri object, and use IsFile to verify it's a file, then Uri.LocalPath to extract the filename.

This is much safer, as it provides you a means to check the validity of the URI as well.


Edit in response to comment:

To get just the full filename, I'd use:

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

This does all of the error checking for you, and is platform-neutral. All of the special cases get handled for you quickly and easily.

Konstantin Yovkov
  • 62,134
  • 8
  • 100
  • 147
Reed Copsey
  • 554,122
  • 78
  • 1,158
  • 1,373
  • I agree, you should really use the Uri class as it already does this stuff for you. +1 – Doctor Jones Jul 09 '09 at 18:17
  • Yup, as simple as it may seem to roll-your-own the Uri class has lots of pre-rolled parsing/validating/encoding goodies in it for you. – STW Jul 09 '09 at 18:23
  • 2
    Right, but I just need the file name, not the complete file path. Aren't I still left to do that step on the Uri.LocalPath? – paulwhit Jul 10 '09 at 17:46
  • 3
    @paulwhit: In that case, you should use Path.GetFileName on the results of Uri.LocalPath. This is a completely safe, highly checked way of handling it. I will edit my answer to include this. See: http://msdn.microsoft.com/en-us/library/system.io.path.getfilename.aspx – Reed Copsey Jul 10 '09 at 17:50
  • Works great for absolute Urls, doesn't work for relative though. The Uri class is very limited when working with relative urls. – tstojecki Sep 17 '09 at 17:08
  • How to do int in wp7, looks like Path.GetFileName is not available. Can anybody advice how to do it? – masiboo Aug 13 '11 at 10:43
  • 55
    isFile appears to only look at the scheme. So: "http://www/myFile.jpg" returns false, "file://www/something.jpg" returns true, so it's useless in this case. – dethSwatch Oct 22 '11 at 16:37
  • @RAJ... I'd just put in a new question – Reed Copsey Jul 06 '12 at 15:43
  • Worth noting that a Uri can contain characters, such as " and <, that cannot be on filesystem paths. The Path class checks for these invalid characters and will throw an exception if they exist. Using Uri.LocalPath does not remove these characters. I wrote up a [post on the issue](http://kamsar.net/index.php/2013/06/a-subtle-error-using-system-io-path-in-a-http-context/) – Kam Figy Jun 16 '13 at 04:37
  • 10
    Also beware of a querystring. `http://www.test.com/file1.txt?a=b` will result in `file1.txt?a=b` – Julian Mar 10 '15 at 12:44
  • Didn't work for `http://url/start.aspx#/_catalogs/masterpage/my.master`, I'm now using: `filename = System.IO.Path.GetFileName(strMasterPageURL.Split('/').Last());` – David Jun 11 '15 at 08:02
  • Also, Path.GetFullPath didn't work for "file://localhost/C:/Users/username/path/to/". I had to add 'path = uri.LocalPath.Replace("\\\\localhost\\", "");'. Not quite as elegant. – James John McGuire 'Jahmic' Sep 25 '16 at 12:58
  • Note: This gives just the filename (as the question asks) NOT a full path... If you are after that try: System.IO.Path.GetFullPath(uri.AbsolutePath); – andrew pate May 23 '17 at 14:12
91

Uri.IsFile doesn't work with http urls. It only works for "file://". From MSDN : "The IsFile property is true when the Scheme property equals UriSchemeFile." So you can't depend on that.

Uri uri = new Uri(hreflink);
string filename = System.IO.Path.GetFileName(uri.LocalPath);
Le Zhang
  • 931
  • 6
  • 5
  • Uri.LocalPath does Windows specific conversions and does not work correctly in a non-Windows environment. See my answer below for a portable way to do this. – Kostub Deshmukh Jan 11 '16 at 19:20
  • While you can't use `Uri.IsFile` to test on a http URL/scheme, you can successfully extract the file name from a http URL using `System.IO.Path.GetFileName(url);` – Alex P. Jan 30 '19 at 09:18
77

Most other answers are either incomplete or don't deal with stuff coming after the path (query string/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);
}

Test results:

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/");              // ""
Michael Armes
  • 1,056
  • 2
  • 17
  • 31
Ronnie Overby
  • 45,287
  • 73
  • 267
  • 346
37

The accepted answer is problematic for http urls. Moreover Uri.LocalPath does Windows specific conversions, and as someone pointed out leaves query strings in there. A better way is to use Uri.AbsolutePath

The correct way to do this for http urls is:

Uri uri = new Uri(hreflink);
string filename = System.IO.Path.GetFileName(uri.AbsolutePath);
Kostub Deshmukh
  • 2,852
  • 2
  • 25
  • 35
  • 9
    Note that for escaped URLs like `http://example.com/dir/hello%20world.txt` this would return `hello%20world.txt` whereas the `Uri.LocalPath` approach would return `hello world.txt` – Jeff Moser Aug 02 '17 at 15:29
26

I think this will do what you need:

var uri = new Uri(hreflink);
var filename = uri.Segments.Last();
Zeus82
  • 6,065
  • 9
  • 53
  • 77
  • 4
    This looks like an elegant solution indeed, but just keep in mind this only works on absolute URIs and returns an encoded/escaped value (use `Uri.UnescapeDataString()` to change %20 and + to spaces). – Ronald Mar 06 '19 at 08:20
8
using System.IO;

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

THis assumes, of course, that you've parsed out the file name.

EDIT #2:

using System.IO;

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

This should handle spaces and the like in the file name.

Mike Hofer
  • 16,477
  • 11
  • 74
  • 110
  • 3
    Colons are not acceptable in paths on all platforms, so this sort of hack might fail on, say, Mono.NET running on a *nix variant. Better to use System.Uri since it is specifically designed to do what the OP needs. – richardtallent Jul 09 '09 at 18:13
  • 1
    A valid point! I always forget about Mono. I thought about spaces and the like, but not the colons. – Mike Hofer Jul 09 '09 at 18:18
6

As of 2020, handles query strings & encoded URLs

public static string GetFileNameFromUrl (string url)
{
    var decoded = HttpUtility.UrlDecode(url);

    if (decoded.IndexOf("?") is {} queryIndex && queryIndex != -1)
    {
        decoded = decoded.Substring(0, queryIndex);
    }

    return Path.GetFileName(decoded);
}
Alexandre Daubricourt
  • 3,323
  • 1
  • 34
  • 33
2

this is my sample you can use:

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

Usage:

var fileName = GetFileNameFromUrl("http://cdn.p30download.com/?b=p30dl-software&f=Mozilla.Firefox.v58.0.x86_p30download.com.zip");
Ali Yousefi
  • 2,355
  • 2
  • 32
  • 47
1

Simple and straight forward:

            Uri uri = new Uri(documentAttachment.DocumentAttachment.PreSignedUrl);
            fileName = Path.GetFileName(uri.LocalPath);
Gregory
  • 6,514
  • 4
  • 28
  • 26
0
  //First Method to get fileName from fileurl  


 List<string> fileNameListValues = new List<string>();  

//fileNameListValues List  consist of fileName and fileUrl 
//we need to get fileName and fileurl from fileNameListValues List 
 name 

 foreach(var items in fileNameListValues)
 {
var fileUrl = items;
var uriPath = new Uri(items).LocalPath;
var fileName = Path.GetFileName(uriPath);
 }


  //Second Way to get filename from fileurl is ->      


 fileNameValue = "https://projectname.com/assets\UploadDocuments\documentFile_637897408013343662.jpg";
 fileName = " documentFile_637897408013343662.jpg";

 //way to get filename from fileurl 

 string filename = 
  fileNameValue.Substring(fileNameValue.LastIndexOf("\\") + 1);
Indian
  • 31
  • 3
  • Do you feel there is there any advantage to doing it this way over the way in the accepted answer? Does it overcome some possible issue with doing it that way? If not, is there another reason this improves upon that answer? – shelleybutterfly May 30 '22 at 16:36