从URL中解析文件名,然后再下载文件。

42

我正在从网址下载一个ePub文件。

现在我想要实现一个机制,如果用户尝试重新下载同一文件,他应该收到警告/错误消息,并且那个文件不应该再次被下载。

为了实现这个机制,我需要检查我的库中的文件名与用户正在尝试下载的文件名是否相同。

但我只有此下载链接,而没有文件名。

如何在下载之前获取文件名以便将其与现有文件进行比较?

6个回答

104
在安卓中,你可以使用 guessFileName() 方法
URLUtil.guessFileName(url, null, null)

或者,Java中的一个简单解决方案可能是:简化版解决方案

String fileName = url.substring(url.lastIndexOf('/') + 1);

(假设您的URL格式为:http://xxxxxxxxxxxxx/filename.ext

2018年3月23日更新

该问题受到了很多访问量,有人评论说我的“简单”解决方案对某些URL无效,因此我觉得有必要改进答案。

如果您想处理更复杂的URL模式,我提供了一个样例解决方案。它很快就变得相当复杂,我十分确信还有一些奇怪的情况我的解决方案仍然无法处理,但是无论如何,以下是解决方案:

public static String getFileNameFromURL(String url) {
    if (url == null) {
        return "";
    }
    try {
        URL resource = new URL(url);
        String host = resource.getHost();
        if (host.length() > 0 && url.endsWith(host)) {
            // handle ...example.com
            return "";
        }
    }
    catch(MalformedURLException e) {
        return "";  
    }

    int startIndex = url.lastIndexOf('/') + 1;
    int length = url.length();

    // find end index for ?
    int lastQMPos = url.lastIndexOf('?');
    if (lastQMPos == -1) {
        lastQMPos = length; 
    }

    // find end index for #
    int lastHashPos = url.lastIndexOf('#');
    if (lastHashPos == -1) {
        lastHashPos = length;   
    }

    // calculate the end index
    int endIndex = Math.min(lastQMPos, lastHashPos);
    return url.substring(startIndex, endIndex);
}

这个方法可以处理这些类型的输入:

Input: "null" Output: ""
Input: "" Output: ""
Input: "file:///home/user/test.html" Output: "test.html"
Input: "file:///home/user/test.html?id=902" Output: "test.html"
Input: "file:///home/user/test.html#footer" Output: "test.html"
Input: "http://example.com" Output: ""
Input: "http://www.example.com" Output: ""
Input: "http://www.example.txt" Output: ""
Input: "http://example.com/" Output: ""
Input: "http://example.com/a/b/c/test.html" Output: "test.html"
Input: "http://example.com/a/b/c/test.html?param=value" Output: "test.html"
Input: "http://example.com/a/b/c/test.html#anchor" Output: "test.html"
Input: "http://example.com/a/b/c/test.html#anchor?param=value" Output: "test.html"

您可以在此处找到完整的源代码:https://ideone.com/uFWxTL


假设我有一个包含书籍集合的链接(例如www.bookstore.com),我从中选择一本书(具有URL www.bookstore.com/book1.epub),应该将其下载到我的图书馆。 我如何获取特定书籍的URL,即www.bookstore.com/book1.epub???webView.getUrl()除了第一次加载之外根本不会触发。 - GAMA
2
你的解决方案仅在没有参数(?param=value)和锚点(#anchor)的情况下有效。 - Tim Autin
非常感谢您的回答,它帮了我很大的忙。 - mochadwi

51

9

保持简单:

/**
 * This function will take an URL as input and return the file name.
 * <p>Examples :</p>
 * <ul>
 * <li>http://example.com/a/b/c/test.txt -> test.txt</li>
 * <li>http://example.com/ -> an empty string </li>
 * <li>http://example.com/test.txt?param=value -> test.txt</li>
 * <li>http://example.com/test.txt#anchor -> test.txt</li>
 * </ul>
 * 
 * @param url The input URL
 * @return The URL file name
 */
public static String getFileNameFromUrl(URL url) {

    String urlString = url.getFile();

    return urlString.substring(urlString.lastIndexOf('/') + 1).split("\\?")[0].split("#")[0];
}

4

我使用它,但不是因为简化事情,使用getPath()可以处理具有查询参数的URL,例如httt://domain.com/file.ext?a=1#anchor,就像@TimAutin一样,但对我来说更易读。 - Davide

2

apache commons-ioFilenameUtils获取文件名

URL url = URL(fileUrl)
String fileName = FilenameUtils.getName(url.getPath())

在build.gradle(app)中添加commons-io依赖项。
implementation "commons-io:commons-io:2.6"

它还可以从复杂的URL中提取文件名,如下所示

http://www.example.com/some/path/to/a/file.xml?foo=bar#test


2
您不必真正比较文件名。只需为具有绝对路径的文件创建< strong>File对象,并检查文件是否存在即可。
protected boolean need2Download(String fileName) {

    File basePath = new File(BOOK_STORE_PATH);

    File fullPath = new File(basePath, fileName);

    if (fullPath.exists())
        return false;
    return true;
}

protected void downloadFile(String url) {
    String fileName = url.substring(url.lastIndexOf('/') + 1);

    if (need2Download(fileName)) {
        // download
    }
}

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