如何从URL中获取文件扩展名?

32

我想知道如何确保从我的脚本下载的文件具有我想要的扩展名。

这些文件不会位于以下 URL:

http://example.com/this_url_will_download_a_file

或许是,但我认为我只会使用那种类型的URL:

http://example.com/file.jpg

因为这是一种非常糟糕的方法,所以我不会使用Url.Substring(Url.LastIndexOf(".") - 3, 3)来检查它。

那么,您建议我怎么做?


我认为你必须以某种方式对其进行子字符串处理,除非先下载文件,然后使用FileSystemObject的GetExtensionName或类似功能。 - David Zemens
1
我已经修改了您的标题,使其不再显示“在 VB.NET 中”。在标题中放置标签是不被推荐的。并添加了“.net”标签,因为任何 .NET 开发人员(VB、C#、IronPython 等)都应该能够提供帮助。 - mason
1
如果_content-type_是答案,那么问题可能是“有没有办法从URL获取文件类型”。 - Software Engineer
4
你是否意识到URL可能没有“文件扩展名”,而任何“扩展名”可能与文件内容毫无关系?你需要关注内容类型,而不是“文件扩展名”。这些扩展名是特定于某些操作系统的,通常不适用于网络。 - John Saunders
那么,如果URL是一个文件呢?例如,我想从Dropbox文件中获取内容类型,目前它可以工作 ;) - z3nth10n
显示剩余7条评论
7个回答

20

这很奇怪,但它有效:

string url = @"http://example.com/file.jpg";
string ext = System.IO.Path.GetExtension(url);
MessageBox.Show(this, ext);

但正如 crono 在下面指出的那样,它不能与参数一起使用:

string url = @"http://example.com/file.jpg?par=x";
string ext = System.IO.Path.GetExtension(url);
MessageBox.Show(this, ext);

结果:".jpg?par=x"


我想这是因为 Microsoft 允许 Unix/Linux 的 "/" 作为目录分隔符,而不仅仅是 ""。几年前,在我参与的一个团队中发现了这一点,这非常令人惊讶,因为旧的 Win32 API 需要使用 "" 作为目录分隔符。可能是因为 Microsoft 正在将东西移植到 .net Core? - John Foll
如果这是真正的实现 GetExtension 方法,那么它仍然可以工作,因为它会向后扫描字符串,直到找到字符点(.)的出现。所以,对于大多数情况来说,斜杠和反斜杠并不重要。 - heringer

18

这里是我使用的一个简单的方法。可以处理参数、绝对和相对URL等等。

public static string GetFileExtensionFromUrl(string url)
{
    url = url.Split('?')[0];
    url = url.Split('/').Last();
    return url.Contains('.') ? url.Substring(url.LastIndexOf('.')) : "";
}

如果您愿意,进行单元测试。

[TestMethod]
public void TestGetExt()
{
    Assert.IsTrue(Helpers.GetFileExtensionFromUrl("../wtf.js?x=wtf")==".js");
    Assert.IsTrue(Helpers.GetFileExtensionFromUrl("wtf.js")==".js");
    Assert.IsTrue(Helpers.GetFileExtensionFromUrl("http://www.com/wtf.js?wtf")==".js");
    Assert.IsTrue(Helpers.GetFileExtensionFromUrl("wtf") == "");
    Assert.IsTrue(Helpers.GetFileExtensionFromUrl("") == "");
}

根据您自己的需求进行调整。

附言:不要使用Path.GetExtension,因为它无法处理查询字符串参数。


这个程序无法处理绝对URL,例如http://www.com/,因为它会将.com作为扩展名返回。 - Joe
@Joe 是的,除非它不是一个“绝对”的URL,而是一个“根”URL。你可能需要添加额外的检查,确保该URL实际上指向一个文件。 - Alex from Jitbit
@Alex 如果我们收到类似于 http://example.com/file 的 URL,结尾没有扩展名,我们该如何确定文件类型? - Roxy'Pro
@Roxy'Pro使用魔数 https://en.wikipedia.org/wiki/Magic_number_(programming)#Magic_numbers_in_files - Alex from Jitbit

5

我知道这是一个老问题,但对于看到这个问题的人可能有帮助。

从URL中获取文件名扩展名的最佳方法,包括参数,是使用正则表达式。

您可以使用以下模式(不仅限于URL):

.+(\.\w{3})\?*.*

解释:

.+     Match any character between one and infinite
(...)  With this, you create a group, after you can use for getting string inside the brackets
\.     Match the character '.'
\w     Matches any word character equal to [a-zA-Z0-9_]
\?*    Match the character '?' between zero and infinite
.*     Match any character between zero and infinite

示例:

http://example.com/file.png
http://example.com/file.png?foo=10

But if you have an URL like this:

http://example.com/asd
This take '.com' as extension.

因此,您可以使用类似以下的强模式来处理URL:

.+\/{2}.+\/{1}.+(\.\w+)\?*.*

说明:

.+        Match any character between one and infinite
\/{2}     Match two '/' characters
.+        Match any character between one and infinite
\/{1}     Match one '/' character
.+        Match any character between one and infinite
(\.\w+)  Group and match '.' character and any word character equal to [a-zA-Z0-9_] from one to infinite
\?*       Match the character '?' between zero and infinite
.*        Match any character between zero and infinite

示例:

http://example.com/file.png          (Match .png)
https://example.com/file.png?foo=10  (Match .png)
http://example.com/asd               (No match)
C:\Foo\file.png                      (No match, only urls!)

http://example.com/file.png

    http:        .+
    //           \/{2}
    example.com  .+
    /            \/{1}
    file         .+
    .png         (\.\w+)

4
这是我的解决方案:
if (Uri.TryCreate(url, UriKind.Absolute, out var uri)){
    Console.WriteLine(Path.GetExtension(uri.LocalPath));
}

首先,我验证我的url是否是有效的url,然后从本地路径中获取文件扩展名。


4

如果你只想获取 http://example.com/file.jpg.jpg 部分,那么只需像 heringer 建议的那样使用 Path.GetExtension

// The following evaluates to ".jpg"
Path.GetExtension("http://example.com/file.jpg")

如果下载链接像这样http://example.com/this_url_will_download_a_file,那么文件名将作为Content-Disposition的一部分包含在其中。它是一个HTTP头,用于向显示“保存文件”对话框的浏览器建议一个文件名。如果您想获取此文件名,则可以使用Get filename without Content-Disposition所提供的技术来启动下载并获取HTTP头,但取消下载而不实际下载任何文件。
HttpWebResponse res = (HttpWebResponse)request.GetResponse();
using (Stream rstream = res.GetResponseStream())
{
    string fileName = res.Headers["Content-Disposition"] != null ?
        res.Headers["Content-Disposition"].Replace("attachment; filename=", "").Replace("\"", "") :
        res.Headers["Location"] != null ? Path.GetFileName(res.Headers["Location"]) : 
        Path.GetFileName(url).Contains('?') || Path.GetFileName(url).Contains('=') ?
        Path.GetFileName(res.ResponseUri.ToString()) : defaultFileName;
}
res.Close();

3
有些人建议从url请求文件并检查头部信息。在我看来,对于如此简单的事情来说,这有点过度了,因此......
如果url上存在参数,则Heringer的答案会失败,解决方案很简单,只需在查询字符串字符“?”上使用Split即可。
string url = @"http://example.com/file.jpg";
string ext = System.IO.Path.GetExtension(url.Split('?')[0]);

0

VirtualPathUtility.GetExtension(yourPath) 返回指定路径中的文件扩展名,包括前导点。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接