Dapatkan nama file dari string URI di C #

206

Saya memiliki metode ini untuk mengambil nama file dari string URI. Apa yang bisa saya lakukan untuk membuatnya lebih kuat?

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
sumber

Jawaban:

388

Anda bisa membuat objek System.Uri, dan menggunakan IsFile untuk memverifikasi itu file, lalu Uri.LocalPath untuk mengekstrak nama file.

Ini jauh lebih aman, karena memberi Anda cara untuk memeriksa validitas URI juga.


Edit dalam menanggapi komentar:

Untuk mendapatkan nama file lengkap, saya akan menggunakan:

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

Ini melakukan semua pengecekan kesalahan untuk Anda, dan platform-netral. Semua kasus khusus ditangani untuk Anda dengan cepat dan mudah.

Reed Copsey
sumber
Saya setuju, Anda harus benar-benar menggunakan kelas Uri karena sudah melakukan hal ini untuk Anda. +1
Dokter Jones
2
Benar, tapi saya hanya perlu nama file, bukan path file lengkap. Bukankah saya masih harus melakukan langkah itu di Uri.LocalPath?
paulwhit
2
@ paulwhit: Dalam hal ini, Anda harus menggunakan Path.GetFileName pada hasil Uri.LocalPath. Ini adalah cara penanganan yang sangat aman dan sangat teruji. Saya akan mengedit jawaban saya untuk memasukkan ini. Lihat: msdn.microsoft.com/en-us/library/…
Reed Copsey
49
isFile tampaknya hanya melihat skema. Jadi: " www / myFile.jpg " mengembalikan false, "file: //www/something.jpg" mengembalikan true, jadi tidak ada gunanya dalam kasus ini.
dethSwatch
6
Waspadalah terhadap querystring. http://www.test.com/file1.txt?a=bakan menghasilkanfile1.txt?a=b
Julian
76

Uri.IsFile tidak berfungsi dengan url http. Ini hanya berfungsi untuk "file: //". Dari MSDN : "Properti IsFile benar ketika properti Scheme sama dengan UriSchemeFile." Jadi Anda tidak bisa bergantung pada itu.

Uri uri = new Uri(hreflink);
string filename = System.IO.Path.GetFileName(uri.LocalPath);
Le Zhang
sumber
Uri.LocalPath melakukan konversi khusus Windows dan tidak berfungsi dengan benar di lingkungan non-Windows. Lihat jawaban saya di bawah ini untuk cara portabel untuk melakukan ini.
Kostub Deshmukh
Meskipun Anda tidak dapat menggunakan Uri.IsFileuntuk menguji pada URL http / skema, Anda dapat berhasil mengekstrak nama file dari URL http menggunakanSystem.IO.Path.GetFileName(url);
Alex Pandrea
50

Sebagian besar jawaban lain tidak lengkap atau tidak berurusan dengan hal-hal yang muncul setelah jalur (string kueri / 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);
}

Hasil tes:

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/");              // ""
Ronnie Overby
sumber
7
Mengapa GetFileNameFromUrl("test")menghasilkan "test.xml" Atau itu hanya salah ketik?
ckittel
27

Jawaban yang diterima bermasalah untuk url http. Selain itu Uri.LocalPathmelakukan konversi khusus Windows, dan ketika seseorang menunjukkan meninggalkan string kueri di sana. Cara yang lebih baik adalah menggunakanUri.AbsolutePath

Cara yang benar untuk melakukan ini untuk url http adalah:

Uri uri = new Uri(hreflink);
string filename = System.IO.Path.GetFileName(uri.AbsolutePath);
Kostub Deshmukh
sumber
7
Perhatikan bahwa untuk URL yang lolos seperti http://example.com/dir/hello%20world.txtini akan kembali hello%20world.txtsedangkan Uri.LocalPathpendekatannya akan kembalihello world.txt
Jeff Moser
22

Saya pikir ini akan melakukan apa yang Anda butuhkan:

var uri = new Uri(hreflink);
var filename = uri.Segments.Last();
Zeus82
sumber
2
Ini memang terlihat seperti solusi yang elegan, tetapi perlu diingat ini hanya bekerja pada URI absolut dan mengembalikan nilai yang dikodekan / lolos (gunakan Uri.UnescapeDataString()untuk mengubah% 20 dan + ke spasi).
Ronald
8
using System.IO;

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

Ini mengasumsikan, tentu saja, bahwa Anda telah menguraikan nama file.

EDIT # 2:

using System.IO;

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

Ini harus menangani spasi dan sejenisnya dalam nama file.

Mike Hofer
sumber
3
Colon tidak dapat diterima di jalur di semua platform, jadi peretasan seperti ini mungkin gagal, katakanlah, Mono.NET berjalan pada varian * nix. Lebih baik menggunakan System.Uri karena dirancang khusus untuk melakukan apa yang dibutuhkan OP.
richardtallent
1
Poin yang valid! Saya selalu melupakan Mono. Saya berpikir tentang ruang dan sejenisnya, tetapi tidak pada titik dua.
Mike Hofer
2

ini adalah sampel saya yang dapat Anda gunakan:

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

Pemakaian:

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

Sederhana dan lurus ke depan:

            Uri uri = new Uri(documentAttachment.DocumentAttachment.PreSignedUrl);
            fileName = Path.GetFileName(uri.LocalPath);
Gregory
sumber