Получить имя файла из URL

В Java, учитывая java.net.URL или String в форме http://www.example.com/some/path/to/a/file.xml , как проще всего получить имя файла без расширения? Итак, в этом примере я ищу что-то, что возвращает "file".

Я могу придумать несколько способов сделать это, но я ищу что-то легко читаемое и короткое.


person Sietse    schedule 03.03.2009    source источник
comment
ВЫ понимаете, что не требуется, чтобы в конце было имя файла или даже что-то похожее на имя файла. В этом случае на сервере может быть или не быть файла .xml.   -  person Miserable Variable    schedule 03.03.2009
comment
в этом случае результатом будет пустая строка или, возможно, ноль.   -  person Sietse    schedule 03.03.2009
comment
Я думаю, вам нужно более четко определить проблему. Как насчет следующих окончаний URL? ..../abc, ..../abc/, ..../abc.def, ..../abc.def.ghi, ..../abc?def.ghi   -  person Miserable Variable    schedule 03.03.2009
comment
Я думаю, это довольно ясно. Если URL-адрес указывает на файл, меня интересует имя файла без расширения (если оно есть). Части запроса выходят за пределы имени файла.   -  person Sietse    schedule 03.03.2009
comment
Клиент не имеет возможности узнать, использует ли сервер файл!   -  person Miserable Variable    schedule 03.03.2009
comment
Вы не определили точно, что вы подразумеваете под именем файла или расширением - и нет, это не те термины, которые все понимают одинаково.   -  person James Moore    schedule 22.05.2012
comment
имя файла является частью URL-адреса после последней косой черты. расширение файла — это часть имени файла после последней точки.   -  person Sietse    schedule 12.06.2012
comment
Вы можете сделать это, используя класс Apache Commons IO FilenameUtils. См. ответ, предоставленный slashnick: stackoverflow.com/questions/8393849/   -  person Spoonface    schedule 23.11.2012
comment
Связанный: stackoverflow.com/questions/4050087/ (содержит лучший ответ, без зависимостей, но не достигает цели удаления расширения.)   -  person Jason C    schedule 06.05.2015


Ответы (24)


Вместо того, чтобы изобретать велосипед, как насчет использования Apache commons-io:

import org.apache.commons.io.FilenameUtils;

public class FilenameUtilTest {

    public static void main(String[] args) throws Exception {
        URL url = new URL("http://www.example.com/some/path/to/a/file.xml?foo=bar#test");

        System.out.println(FilenameUtils.getBaseName(url.getPath())); // -> file
        System.out.println(FilenameUtils.getExtension(url.getPath())); // -> xml
        System.out.println(FilenameUtils.getName(url.getPath())); // -> file.xml
    }

}
person Adrian B.    schedule 18.06.2013
comment
По крайней мере, в версии commons-io 2.2 вам все еще нужно вручную обрабатывать URL-адреса с параметрами. Например. example.com/file.xml?date=2010-10-20 - person Luke Quinane; 13.08.2013
comment
да @LukeQuinane, похоже, это не обрабатывает URL-адреса с параметрами запроса :( - person Sebastien Lorber; 18.04.2014
comment
FilenameUtils.getName(url) подходит лучше. - person ehsun7b; 22.04.2014
comment
Кажется странным добавлять зависимость от commons-io, когда простые решения легко доступны, просто используя JDK (см. URL#getPath и String#substring или Path#getFileName или File#getName). - person Jason C; 06.05.2015
comment
Я вижу, что на это решение ссылаются везде, когда оно не решает проблему работы со строками запросов. - person Marc; 30.06.2015
comment
Класс FilenameUtils предназначен для работы с Windows и путями *nix, а не с URL-адресами. - person nhahtdh; 29.07.2015
comment
по умолчанию мы не можем его использовать, мы должны импортировать библиотеку... compile 'commons-io:commons-io:2.4' для Gradle и <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.4</version> </dependency> для maven - person Choletski; 22.10.2015
comment
Обновленный пример для использования URL-адреса, показа образцов выходных значений и использования параметров запроса. - person Nick Grealy; 28.10.2016
comment
FilenameUtils.getName может время от времени возвращать нежелательные результаты. Дополнительная информация здесь, в другом ответе на этой странице - person Brad Parks; 22.01.2018
comment
Это решение не учитывает заголовок content-disposition, который должен сделать запрос к URL-адресу. - person djmj; 30.01.2018
comment
Поскольку я получаю unable to resolve class org.apache.commons.io.FilenameUtils, это решение не подходит для каждой среды. - person Erik Aigner; 07.06.2018
comment
@Kronen, вопрос касается Java, а не сторонних библиотек. - person Erik Aigner; 24.10.2018
comment
@Erik Aigner Apache commons-io - это библиотека Java, а не библиотека C # или Python, вопрос вообще не ограничивает ответы стандартной библиотекой. - person Kronen; 24.10.2018

Если вам не нужно избавляться от расширения файла, вот способ сделать это, не прибегая к подверженным ошибкам манипуляциям со строками и без использования внешних библиотек. Работает с Java 1.7+:

import java.net.URI
import java.nio.file.Paths

String url = "http://example.org/file?p=foo&q=bar"
String filename = Paths.get(new URI(url).getPath()).getFileName().toString()
person Zoltán    schedule 23.11.2015
comment
@Carcigenicate Я только что проверил это снова, и, кажется, все работает нормально. URI.getPath() возвращает String, поэтому я не понимаю, почему это не сработает - person Zoltán; 23.03.2018
comment
Нвм. Теперь я понимаю, что моя проблема была связана с тем, как Clojure обрабатывает var-args во время взаимодействия с Java. Перегрузка String не работала, потому что для обработки var-args Paths/get также необходимо было передать пустой массив. Однако это все еще работает, если вы избавитесь от вызова getPath и вместо этого используете перегрузку URI. - person Carcigenicate; 23.03.2018
comment
@Carcigenicate, ты имеешь в виду Paths.get(new URI(url))? Кажется, это не работает для меня. - person Zoltán; 11.01.2019
comment
getFileName требует Android API уровня 26 - person Manuela; 12.03.2020

Это должно сократить его (я оставлю вам обработку ошибок):

int slashIndex = url.lastIndexOf('/');
int dotIndex = url.lastIndexOf('.', slashIndex);
String filenameWithoutExtension;
if (dotIndex == -1) {
  filenameWithoutExtension = url.substring(slashIndex + 1);
} else {
  filenameWithoutExtension = url.substring(slashIndex + 1, dotIndex);
}
person tehvan    schedule 03.03.2009
comment
Один аспект обработки ошибок, который вам необходимо учитывать, заключается в том, что вы получите пустую строку, если случайно передадите ей URL-адрес, у которого нет имени файла (например, http://www.example.com/ или http://www.example.com/folder/). - person rtpHarry; 21.01.2011
comment
Код не работает. lastIndexOf так не работает. Но намерение ясно. - person Robert; 15.12.2011
comment
Отклонено, потому что это не будет работать, если часть фрагмента содержит косые черты, и потому что есть специальные функции, которые достигают этого в apache commons и в Java, начиная с 1.7. - person Zoltán; 31.05.2018

Один лайнер:

new File(uri.getPath).getName

Полный код (в scala REPL):

import java.io.File
import java.net.URI

val uri = new URI("http://example.org/file.txt?whatever")

new File(uri.getPath).getName
res18: String = file.txt

Примечание: URI#gePath уже достаточно умен, чтобы убрать параметры запроса и схему протокола. Примеры:

new URI("http://example.org/hey/file.txt?whatever").getPath
res20: String = /hey/file.txt

new URI("hdfs:///hey/file.txt").getPath
res21: String = /hey/file.txt

new URI("file:///hey/file.txt").getPath
res22: String = /hey/file.txt
person juanmirocks    schedule 08.11.2017
comment
хорошее решение! - person CybeX; 22.01.2018
comment
это лучший вариант, так как он использует только стандартный JDK - person Alexandros; 19.04.2018

Получить файл Имя с расширением, без расширения, только расширение всего из 3 строк:

String urlStr = "http://www.example.com/yourpath/foler/test.png";

String fileName = urlStr.substring(urlStr.lastIndexOf('/')+1, urlStr.length());
String fileNameWithoutExtension = fileName.substring(0, fileName.lastIndexOf('.'));
String fileExtension = urlStr.substring(urlStr.lastIndexOf("."));

Log.i("File Name", fileName);
Log.i("File Name Without Extension", fileNameWithoutExtension);
Log.i("File Extension", fileExtension);

Результат журнала:

File Name(13656): test.png
File Name Without Extension(13656): test
File Extension(13656): .png

Надеюсь, это поможет вам.

person Hiren Patel    schedule 17.07.2015

Я придумал это:

String url = "http://www.example.com/some/path/to/a/file.xml";
String file = url.substring(url.lastIndexOf('/')+1, url.lastIndexOf('.'));
person Sietse    schedule 03.03.2009
comment
Или по URL без файла, только путь. - person Sietse; 03.03.2009
comment
ваш код тоже правильный. в любом случае мы не должны проверять отрицательные условия. голосование за вас. Кстати, имя Дирк Куйт звучит знакомо? - person Real Red.; 03.03.2009

Будь проще :

/**
 * 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];
}
person Tim Autin    schedule 07.11.2014
comment
@AlexNauda Замените url.getFile() на url.toString(), и он будет работать с # в пути. - person Sormuras; 14.05.2017

Есть несколько способов:

Файловый ввод-вывод Java 7:

String fileName = Paths.get(strUrl).getFileName().toString();

Общие ресурсы Apache:

String fileName = FilenameUtils.getName(strUrl);

Использование Джерси:

UriBuilder buildURI = UriBuilder.fromUri(strUrl);
URI uri = buildURI.build();
String fileName = Paths.get(uri.getPath()).getFileName();

Подстрока:

String fileName = strUrl.substring(strUrl.lastIndexOf('/') + 1);
person Giang Phan    schedule 07.07.2018
comment
К сожалению, ваше решение Java 7 File I/O мне не подходит. У меня есть исключение. У меня это получается: Paths.get(new URL(strUrl).getFile()).getFileName().toString(); Спасибо за идею! - person Sergey Nemchinov; 07.09.2019

Вот самый простой способ сделать это в Android. Я знаю, что это не будет работать на Java, но может помочь разработчику приложений для Android.

import android.webkit.URLUtil;

public String getFileNameFromURL(String url) {
    String fileNameWithExtension = null;
    String fileNameWithoutExtension = null;
    if (URLUtil.isValidUrl(url)) {
        fileNameWithExtension = URLUtil.guessFileName(url, null, null);
        if (fileNameWithExtension != null && !fileNameWithExtension.isEmpty()) {
            String[] f = fileNameWithExtension.split(".");
            if (f != null & f.length > 1) {
                fileNameWithoutExtension = f[0];
            }
        }
    }
    return fileNameWithoutExtension;
}
person Bharat Dodeja    schedule 11.10.2013

Создайте объект URL из строки. Когда у вас есть объект URL, есть методы, позволяющие легко извлечь практически любой фрагмент информации, который вам нужен.

Я могу настоятельно рекомендовать веб-сайт Javaalmanac, на котором есть множество примеров, но который с тех пор переехал. Вы можете найти http://exampledepot.8waytrips.com/egs/java.io/File2Uri.html интересно:

// Create a file object
File file = new File("filename");

// Convert the file object to a URL
URL url = null;
try {
    // The file need not exist. It is made into an absolute path
    // by prefixing the current working directory
    url = file.toURL();          // file:/d:/almanac1.4/java.io/filename
} catch (MalformedURLException e) {
}

// Convert the URL to a file object
file = new File(url.getFile());  // d:/almanac1.4/java.io/filename

// Read the file contents using the URL
try {
    // Open an input stream
    InputStream is = url.openStream();

    // Read from is

    is.close();
} catch (IOException e) {
    // Could not open the file
}
person Thorbjørn Ravn Andersen    schedule 03.03.2009

Если вы хотите получить только имя файла из java.net.URL (не включая какие-либо параметры запроса), вы можете использовать следующую функцию:

public static String getFilenameFromURL(URL url) {
    return new File(url.getPath().toString()).getName();
}

Например, этот входной URL:

"http://example.com/image.png?version=2&amp;modificationDate=1449846324000"

Будет переведено в эту выходную строку:

image.png
person dokaspar    schedule 25.08.2016

Я обнаружил, что некоторые URL-адреса, переданные непосредственно в FilenameUtils.getName, возвращают нежелательные результаты, и это необходимо обернуть, чтобы избежать эксплойтов.

Например,

System.out.println(FilenameUtils.getName("http://www.google.com/.."));

возвращается

..

что я сомневаюсь, что кто-то хочет разрешить.

Следующая функция, кажется, работает нормально и показывает некоторые из этих тестовых случаев, и возвращает null, когда имя файла не может быть определено.

public static String getFilenameFromUrl(String url)
{
    if (url == null)
        return null;
    
    try
    {
        // Add a protocol if none found
        if (! url.contains("//"))
            url = "http://" + url;

        URL uri = new URL(url);
        String result = FilenameUtils.getName(uri.getPath());

        if (result == null || result.isEmpty())
            return null;

        if (result.contains(".."))
            return null;

        return result;
    }
    catch (MalformedURLException e)
    {
        return null;
    }
}

Это завершается несколькими простыми тестовыми случаями в следующем примере:

import java.util.Objects;
import java.net.URL;
import org.apache.commons.io.FilenameUtils;

class Main {

  public static void main(String[] args) {
    validateFilename(null, null);
    validateFilename("", null);
    validateFilename("www.google.com/../me/you?trex=5#sdf", "you");
    validateFilename("www.google.com/../me/you?trex=5 is the num#sdf", "you");
    validateFilename("http://www.google.com/test.png?test", "test.png");
    validateFilename("http://www.google.com", null);
    validateFilename("http://www.google.com#test", null);
    validateFilename("http://www.google.com////", null);
    validateFilename("www.google.com/..", null);
    validateFilename("http://www.google.com/..", null);
    validateFilename("http://www.google.com/test", "test");
    validateFilename("https://www.google.com/../../test.png", "test.png");
    validateFilename("file://www.google.com/test.png", "test.png");
    validateFilename("file://www.google.com/../me/you?trex=5", "you");
    validateFilename("file://www.google.com/../me/you?trex", "you");
  }

  private static void validateFilename(String url, String expectedFilename){
    String actualFilename = getFilenameFromUrl(url);

    System.out.println("");
    System.out.println("url:" + url);
    System.out.println("filename:" + expectedFilename);

    if (! Objects.equals(actualFilename, expectedFilename))
      throw new RuntimeException("Problem, actual=" + actualFilename + " and expected=" + expectedFilename + " are not equal");
  }

  public static String getFilenameFromUrl(String url)
  {
    if (url == null)
      return null;

    try
    {
      // Add a protocol if none found
      if (! url.contains("//"))
        url = "http://" + url;

      URL uri = new URL(url);
      String result = FilenameUtils.getName(uri.getPath());

      if (result == null || result.isEmpty())
        return null;

      if (result.contains(".."))
        return null;

      return result;
    }
    catch (MalformedURLException e)
    {
      return null;
    }
  }
}
person Brad Parks    schedule 20.12.2016

URL-адреса могут иметь параметры в конце, это

 /**
 * Getting file name from url without extension
 * @param url string
 * @return file name
 */
public static String getFileName(String url) {
    String fileName;
    int slashIndex = url.lastIndexOf("/");
    int qIndex = url.lastIndexOf("?");
    if (qIndex > slashIndex) {//if has parameters
        fileName = url.substring(slashIndex + 1, qIndex);
    } else {
        fileName = url.substring(slashIndex + 1);
    }
    if (fileName.contains(".")) {
        fileName = fileName.substring(0, fileName.lastIndexOf("."));
    }

    return fileName;
}
person Serhii Bohutskyi    schedule 31.10.2013
comment
/ может появиться во фрагменте. Вы будете извлекать не тот материал. - person nhahtdh; 29.07.2015

Объект Url в urllib позволяет получить доступ к неэкранированному имени файла пути. Вот некоторые примеры:

String raw = "http://www.example.com/some/path/to/a/file.xml";
assertEquals("file.xml", Url.parse(raw).path().filename());

raw = "http://www.example.com/files/r%C3%A9sum%C3%A9.pdf";
assertEquals("résumé.pdf", Url.parse(raw).path().filename());
person EricE    schedule 12.11.2017

ответ Энди переделан с использованием split():

Url u= ...;
String[] pathparts= u.getPath().split("\\/");
String filename= pathparts[pathparts.length-1].split("\\.", 1)[0];
person bobince    schedule 03.03.2009

Как насчет этого:

String filenameWithoutExtension = null;
String fullname = new File(
    new URI("http://www.xyz.com/some/deep/path/to/abc.png").getPath()).getName();

int lastIndexOfDot = fullname.lastIndexOf('.');
filenameWithoutExtension = fullname.substring(0, 
    lastIndexOfDot == -1 ? fullname.length() : lastIndexOfDot);
person Leon    schedule 15.06.2013

Чтобы вернуть имя файла без расширения и без параметров, используйте следующее:

String filenameWithParams = FilenameUtils.getBaseName(urlStr); // may hold params if http://example.com/a?param=yes
return filenameWithParams.split("\\?")[0]; // removing parameters from url if they exist

Чтобы вернуть имя файла с расширением без параметров, используйте это:

/** Parses a URL and extracts the filename from it or returns an empty string (if filename is non existent in the url) <br/>
 * This method will work in win/unix formats, will work with mixed case of slashes (forward and backward) <br/>
 * This method will remove parameters after the extension
 *
 * @param urlStr original url string from which we will extract the filename
 * @return filename from the url if it exists, or an empty string in all other cases */
private String getFileNameFromUrl(String urlStr) {
    String baseName = FilenameUtils.getBaseName(urlStr);
    String extension = FilenameUtils.getExtension(urlStr);

    try {
        extension = extension.split("\\?")[0]; // removing parameters from url if they exist
        return baseName.isEmpty() ? "" : baseName + "." + extension;
    } catch (NullPointerException npe) {
        return "";
    }
}
person Chaiavi    schedule 18.08.2014

Помимо всех продвинутых методов, мой простой трюк StringTokenizer:

import java.util.ArrayList;
import java.util.StringTokenizer;

public class URLName {
    public static void main(String args[]){
        String url = "http://www.example.com/some/path/to/a/file.xml";
        StringTokenizer tokens = new StringTokenizer(url, "/");

        ArrayList<String> parts = new ArrayList<>();

        while(tokens.hasMoreTokens()){
            parts.add(tokens.nextToken());
        }
        String file = parts.get(parts.size() -1);
        int dot = file.indexOf(".");
        String fileName = file.substring(0, dot);
        System.out.println(fileName);
    }
}
person Blasanka    schedule 31.05.2017

Если вы используете Spring, существует помощник для обработки URI. Вот решение:

List<String> pathSegments = UriComponentsBuilder.fromUriString(url).build().getPathSegments();
String filename = pathSegments.get(pathSegments.size()-1);
person Benjamin Caure    schedule 04.09.2019

вернуть новый файл (Uri.parse (url). getPath ()). getName ()

person GangrenaGastrit    schedule 11.03.2020

У меня такая же проблема, с твоей. Я решил это следующим образом:

var URL = window.location.pathname; // Gets page name
var page = URL.substring(URL.lastIndexOf('/') + 1); 
console.info(page)
person Via Marie Inte    schedule 11.02.2019
comment
Java — это не JavaScript - person nathanfranke; 23.02.2020

импортировать java.io.*;

import java.net.*;

public class ConvertURLToFileName{


   public static void main(String[] args)throws IOException{
   BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
   System.out.print("Please enter the URL : ");

   String str = in.readLine();


   try{

     URL url = new URL(str);

     System.out.println("File : "+ url.getFile());
     System.out.println("Converting process Successfully");

   }  
   catch (MalformedURLException me){

      System.out.println("Converting process error");

 }

Я надеюсь, что это поможет вам.

person Ricardo Felgueiras    schedule 03.03.2009
comment
getFile() делает не то, что вы думаете. Согласно документу, на самом деле это getPath()+getQuery, что довольно бессмысленно. java.sun.com/ j2se/1.4.2/docs/api/java/net/URL.html#getFile() - person bobince; 03.03.2009

person    schedule
comment
Почему минус? Это нечестно. Мой код работает, я только что проверил свой код, увидев минус. - person Real Red.; 03.03.2009
comment
Я проголосовал за вас, потому что это немного более читабельно, чем моя версия. Понижение может быть связано с тем, что оно не работает, когда нет расширения или файла. - person Sietse; 03.03.2009
comment
Вы можете оставить второй параметр до substring() - person Jon Onstott; 07.12.2014
comment
Это не работает ни для http://example.org/file#anchor, ни для http://example.org/file?p=foo&q=bar, ни для http://example.org/file.xml#/p=foo&q=bar - person Matthias Ronge; 29.01.2015
comment
Если вы разрешите String url = new URL(original_url).getPath() и добавите специальный регистр для имен файлов, которые не содержат ., тогда это работает нормально. - person Jason C; 06.05.2015
comment
Отклонено, потому что это не будет работать, если часть фрагмента содержит косые черты, и потому что есть специальные функции, которые достигают этого в apache commons и в Java, начиная с 1.7. - person Zoltán; 31.05.2018
comment
Пользовательские манипуляции со строками в URL-адресах — это всегда ужасная идея. Что делать, если в системе разные разделители? Нравится \ или :? - person Erik Aigner; 07.06.2018

person    schedule
comment
Не работает, если строка запроса содержит / (и поверьте, может). - person maaw; 15.12.2020
comment
@maaw, пожалуйста, поделитесь одним примером - person Yogesh Rathi; 16.12.2020
comment
то вы можете добавить дополнительную проверку для отдельного запроса. - person Yogesh Rathi; 17.12.2020