รับชื่อไฟล์จากสตริง 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 Copsey

49
isFile ปรากฏขึ้นเพื่อดูรูปแบบเท่านั้น ดังนั้น: " www / myFile.jpg " คืนค่าเท็จ "file: //www/something.jpg" คืนค่าจริงดังนั้นจึงไม่มีประโยชน์ในกรณีนี้
dethSwatch

6
ยังระวังการสอบถาม http://www.test.com/file1.txt?a=bจะส่งผลให้file1.txt?a=b
Julian

76

Uri.IsFile ใช้ไม่ได้กับ URL URL ใช้งานได้กับ "file: //" เท่านั้น จากMSDN : "คุณสมบัติ IsFile เป็นจริงเมื่อคุณสมบัติ Scheme เท่ากับ UriSchemeFile" ดังนั้นคุณไม่สามารถพึ่งพาสิ่งนั้นได้

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

Uri.LocalPath ทำการแปลงเฉพาะของ Windows และทำงานไม่ถูกต้องในสภาพแวดล้อมที่ไม่ใช่ Windows ดูคำตอบของฉันด้านล่างสำหรับวิธีพกพาในการทำเช่นนี้
Kostub Deshmukh

ในขณะที่คุณไม่สามารถใช้Uri.IsFileทดสอบ URL / โครงร่าง http ได้ แต่คุณสามารถแตกชื่อไฟล์จาก http URL ได้โดยใช้System.IO.Path.GetFileName(url);
Alex

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 URL นอกจากนี้ยังUri.LocalPathทำการแปลงเฉพาะ Windows และเป็นคนชี้ให้ออกสตริงการสืบค้นในนั้น วิธีที่ดีกว่าคือการใช้Uri.AbsolutePath

วิธีที่ถูกต้องในการทำเช่นนี้กับ URL URL คือ:

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
นี่ดูเหมือนเป็นโซลูชันที่สวยงาม แต่โปรดจำไว้ว่านี่ใช้ได้เฉพาะกับ URIs ที่สมบูรณ์และส่งคืนค่าที่เข้ารหัส / หลบหนี (ใช้Uri.UnescapeDataString()เพื่อเปลี่ยน% 20 และ + เป็นช่องว่าง)
Ronald

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 เนื่องจากมันถูกออกแบบมาโดยเฉพาะเพื่อทำสิ่งที่ OP ต้องการ
richardtallent

1
จุดที่ถูกต้อง! ฉันมักจะลืมโมโน ฉันคิดถึงพื้นที่และสิ่งที่คล้ายกัน แต่ไม่ใช่โคลอน
Mike Hofer

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

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.