GAMA
GAMA

Reputation: 5996

Parse file name from URL before downloading the file

I'm downloading an ePub file from a URL.

Now I want to implement a mechanism by which if user tries to re-download the same file, he should get warning/error message and that file should not be downloaded again.

To implement this, I need to check the name of the file present in my library with the name of the file user is trying to download.

But I just have this download link, and not the file name.

How to get the name of the file before download in order to compare it with the existing file?

Upvotes: 42

Views: 47412

Answers (6)

Naveen Kumar M
Naveen Kumar M

Reputation: 7557

Get file name from FilenameUtils from apache commons-io

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

To this add commons-io dependency in build.gradle(app)

implementation "commons-io:commons-io:2.6"

It also extracts the file name from the complex URL like below

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

Upvotes: 2

Caner
Caner

Reputation: 59168

In android you can use the guessFileName() method:

URLUtil.guessFileName(url, null, null)

Alternatively, a simplistic solution in Java could be:

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

(Assuming your url is in the format: http://xxxxxxxxxxxxx/filename.ext)

UPDATE March 23, 2018

This question is getting lots of hits and someone commented my 'simple' solution does not work with certain urls so I felt the need to improve the answer.

In case you want to handle more complex url pattern, I provided a sample solution below. It gets pretty complex quite quickly and I'm pretty sure there are some odd cases my solution still can't handle but nevertheless here it goes:

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

This method can handle these type of input:

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"

You can find the whole source code here: https://ideone.com/uFWxTL

Upvotes: 107

Himanshu Shekhar
Himanshu Shekhar

Reputation: 447

I think using URL#getPath() should simplify things.

public static String getFileNameFromUrl(URL url) {

    String urlPath = url.getPath();

    return urlPath.substring(urlPath.lastIndexOf('/') + 1);
}

See, http://developer.android.com/reference/java/net/URL.html#getPath()

Upvotes: 4

sealskej
sealskej

Reputation: 7421

Try to use URLUtil.guessFileName(url, null, null) for example. I think this is the best Android way.

More info here: https://developer.android.com/reference/android/webkit/URLUtil.html#guessFileName(java.lang.String, java.lang.String, java.lang.String)

Upvotes: 51

Tim Autin
Tim Autin

Reputation: 6165

Keep it simple :

/**
 * 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];
}

Upvotes: 9

Shiv
Shiv

Reputation: 1267

You dont really have to compare file names. Just make File object for the file with absolute path and check if file exists.

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

Upvotes: 2

Related Questions