Obtener el nombre del archivo de la URL

146

En Java, dada una java.net.URLo una Stringen forma de http://www.example.com/some/path/to/a/file.xml, ¿cuál es la forma más fácil de obtener el nombre del archivo, menos la extensión? Entonces, en este ejemplo, estoy buscando algo que regrese "file".

Se me ocurren varias formas de hacerlo, pero estoy buscando algo que sea fácil de leer y breve.

Sietse
fuente
3
USTED se da cuenta de que no hay ningún requisito para que haya un nombre de archivo al final, o incluso algo que se parezca a un nombre de archivo. En este caso, puede haber o no un archivo.xml en el servidor.
Variable miserable
2
en ese caso, el resultado sería una cadena vacía, o tal vez nula.
Sietse
1
Creo que necesitas definir el problema más claramente. ¿Qué pasa con las siguientes terminaciones de URLS? .... / abc, .... / abc /, .... / abc.def, .... / abc.def.ghi, .... / abc? def.ghi
Variable miserable
2
Creo que está bastante claro. Si la URL apunta a un archivo, estoy interesado en el nombre del archivo menos la extensión (si tiene uno). Las partes de consulta quedan fuera del nombre del archivo.
Sietse
44
el nombre del archivo es la parte de la url después de la última barra inclinada. la extensión del archivo es la parte del nombre del archivo después del último período.
Sietse

Respuestas:

188

En lugar de reinventar la rueda, ¿qué tal usar 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
    }

}
Adrian B.
fuente
2
En la versión commons-io 2.2, al menos, aún necesita manejar manualmente las URL con parámetros. Por ejemplo, " example.com/file.xml?date=2010-10-20 "
Luke Quinane
18
FilenameUtils.getName (url) se ajusta mejor.
ehsun7b
44
Parece extraño agregar una dependencia de commons-io cuando hay soluciones fáciles disponibles con solo usar el JDK (ver URL#getPathy String#substring/ Path#getFileNameo File#getName).
Jason C
55
La clase FilenameUtils está diseñada para funcionar con Windows y la ruta * nix, no URL.
nhahtdh
44
Ejemplo actualizado para usar una URL, mostrar valores de salida de muestra y usar parámetros de consulta.
Nick Grealy
191
String fileName = url.substring( url.lastIndexOf('/')+1, url.length() );

String fileNameWithoutExtn = fileName.substring(0, fileName.lastIndexOf('.'));
Rojo real.
fuente
17
¿Por qué el voto negativo? Esto es injusto. Mi código funciona, acabo de verificar mi código después de ver el voto negativo.
Real Red.
2
Te voté porque es un poco más legible que mi versión. El voto negativo puede deberse a que no funciona cuando no hay extensión ni archivo.
Sietse
1
Puede dejar el segundo parámetro parasubstring()
Jon Onstott
12
Esto no funciona para ninguno de los dos http://example.org/file#anchor, http://example.org/file?p=foo&q=barnihttp://example.org/file.xml#/p=foo&q=bar
Matthias Ronge el
2
Si deja String url = new URL(original_url).getPath()y agrega un caso especial para nombres de archivo que no contienen un, .entonces esto funciona bien.
Jason C
32

Si no necesita deshacerse de la extensión de archivo, aquí hay una manera de hacerlo sin recurrir a la manipulación de cadenas propensa a errores y sin usar bibliotecas externas. Funciona con 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()
Zoltán
fuente
1
@Carcigenicate Lo probé nuevamente y parece funcionar bien. URI.getPath()devuelve un String, así que no veo por qué no funcionaría
Zoltán
1
Nvm. Ahora me doy cuenta de que mi problema se debió a cómo Clojure maneja var-args durante la interoperabilidad de Java. La sobrecarga de String no funcionaba porque también era necesario pasar una matriz vacía para manejar los var-args de Paths / get. Sin embargo, todavía funciona si se deshace de la llamada getPathy usa la sobrecarga de URI en su lugar.
Carcigenicate
@Carcigenicate quieres decir Paths.get(new URI(url))? Eso no parece funcionar para mí
Zoltán
getFileName requiere una API de Android de nivel 26
Manuela
26

Esto debería cortarlo (te dejaré el manejo de errores):

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);
}
Tehvan
fuente
1
Un aspecto de manejo de errores que debe considerar es que terminará con una cadena vacía si accidentalmente le pasa una url que no tiene un nombre de archivo (como http://www.example.com/o http://www.example.com/folder/)
rtpHarry
2
El código no funciona. lastIndexOfno funciona de esta manera Pero la intención es clara.
Robert
Votado en contra porque no funcionará si la parte del fragmento contiene barras diagonales, y porque hay funciones dedicadas que logran esto en apache commons y en Java desde 1.7
Zoltán
14
public static String getFileName(URL extUrl) {
        //URL: "http://photosaaaaa.net/photos-ak-snc1/v315/224/13/659629384/s659629384_752969_4472.jpg"
        String filename = "";
        //PATH: /photos-ak-snc1/v315/224/13/659629384/s659629384_752969_4472.jpg
        String path = extUrl.getPath();
        //Checks for both forward and/or backslash 
        //NOTE:**While backslashes are not supported in URL's 
        //most browsers will autoreplace them with forward slashes
        //So technically if you're parsing an html page you could run into 
        //a backslash , so i'm accounting for them here;
        String[] pathContents = path.split("[\\\\/]");
        if(pathContents != null){
            int pathContentsLength = pathContents.length;
            System.out.println("Path Contents Length: " + pathContentsLength);
            for (int i = 0; i < pathContents.length; i++) {
                System.out.println("Path " + i + ": " + pathContents[i]);
            }
            //lastPart: s659629384_752969_4472.jpg
            String lastPart = pathContents[pathContentsLength-1];
            String[] lastPartContents = lastPart.split("\\.");
            if(lastPartContents != null && lastPartContents.length > 1){
                int lastPartContentLength = lastPartContents.length;
                System.out.println("Last Part Length: " + lastPartContentLength);
                //filenames can contain . , so we assume everything before
                //the last . is the name, everything after the last . is the 
                //extension
                String name = "";
                for (int i = 0; i < lastPartContentLength; i++) {
                    System.out.println("Last Part " + i + ": "+ lastPartContents[i]);
                    if(i < (lastPartContents.length -1)){
                        name += lastPartContents[i] ;
                        if(i < (lastPartContentLength -2)){
                            name += ".";
                        }
                    }
                }
                String extension = lastPartContents[lastPartContentLength -1];
                filename = name + "." +extension;
                System.out.println("Name: " + name);
                System.out.println("Extension: " + extension);
                System.out.println("Filename: " + filename);
            }
        }
        return filename;
    }
Miguel
fuente
13

Un trazador de líneas:

new File(uri.getPath).getName

Código completo (en una escala 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

Nota : URI#gePathya es lo suficientemente inteligente como para quitar los parámetros de consulta y el esquema del protocolo. Ejemplos:

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
juanmirocks
fuente
1
buena solución!
CybeX
1
esta es la mejor opción, ya que solo utiliza JDK estándar
Alexandros
11

Obtenga el nombre del archivo con extensión , sin extensión , solo extensión con solo 3 líneas:

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

Resultado del registro:

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

Espero que te ayude.

Hiren Patel
fuente
9

Se me ocurrió esto:

String url = "http://www.example.com/some/path/to/a/file.xml";
String file = url.substring(url.lastIndexOf('/')+1, url.lastIndexOf('.'));
Sietse
fuente
O en URL sin archivo, solo una ruta.
Sietse
Tu código también es correcto. se supone que no debemos verificar las condiciones negativas de todos modos. Un voto a favor para ti. por cierto, ¿te suena familiar el nombre dirk kuyt?
Real Red.
8

Hay algunas formas:

E / S de archivos Java 7:

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

Apache Commons:

String fileName = FilenameUtils.getName(strUrl);

Usando Jersey:

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

Subcadena:

String fileName = strUrl.substring(strUrl.lastIndexOf('/') + 1);
Giang Phan
fuente
Desafortunadamente, su solución de E / S de archivos Java 7 no funciona para mí. Tengo una excepción Tengo éxito con esto: ¡ Paths.get(new URL(strUrl).getFile()).getFileName().toString(); Gracias por la idea!
Sergey Nemchinov
7

Mantenlo 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];
}
Tim Autin
fuente
1
@AlexNauda Reemplace url.getFile()con url.toString()y funciona con #en la ruta.
Sormuras
7
String fileName = url.substring(url.lastIndexOf('/') + 1);
Yogesh Rathi
fuente
5

Aquí está la forma más sencilla de hacerlo en Android. Sé que no funcionará en Java, pero puede ayudar al desarrollador de aplicaciones de 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;
}
Bharat Dodeja
fuente
3

Cree un objeto URL a partir de la cadena. Cuando tiene un objeto URL por primera vez, existen métodos para extraer fácilmente cualquier fragmento de información que necesite.

Puedo recomendar encarecidamente el sitio web Javaalmanac que tiene toneladas de ejemplos, pero que desde entonces se ha mudado. Puede encontrar http://exampledepot.8waytrips.com/egs/java.io/File2Uri.html interesante:

// 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
}
Thorbjørn Ravn Andersen
fuente
2

Si desea obtener solo el nombre de archivo de un java.net.URL (sin incluir ningún parámetro de consulta), puede usar la siguiente función:

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

Por ejemplo, esta URL de entrada:

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

Sería traducido a esta cadena de salida:

image.png
dokaspar
fuente
2

Descubrí que algunas URL se pasan directamente a FilenameUtils.getName devolver resultados no deseados y esto debe ser cerrado para evitar exploits.

Por ejemplo,

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

devoluciones

..

que dudo que alguien quiera permitir.

La siguiente función parece funcionar bien y muestra algunos de estos casos de prueba, y regresa nullcuando no se puede determinar el nombre de archivo.

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

Esto está envuelto con algunos casos de pruebas simples en el siguiente ejemplo:

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;
    }
  }
}
Brad Parks
fuente
1

Las URL pueden tener parámetros al final, esto

 /**
 * 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;
}
Serhii Bohutskyi
fuente
/Puede aparecer en fragmentos. Extraerás las cosas incorrectas.
nhahtdh
1

El Urlobjeto en urllib le permite acceder al nombre de archivo sin escape de la ruta. Aquí hay unos ejemplos:

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());
EricE
fuente
0

La respuesta de Andy se rehizo usando split ():

Url u= ...;
String[] pathparts= u.getPath().split("\\/");
String filename= pathparts[pathparts.length-1].split("\\.", 1)[0];
bobince
fuente
0
public String getFileNameWithoutExtension(URL url) {
    String path = url.getPath();

    if (StringUtils.isBlank(path)) {
        return null;
    }
    if (StringUtils.endsWith(path, "/")) {
        //is a directory ..
        return null;
    }

    File file = new File(url.getPath());
    String fileNameWithExt = file.getName();

    int sepPosition = fileNameWithExt.lastIndexOf(".");
    String fileNameWithOutExt = null;
    if (sepPosition >= 0) {
        fileNameWithOutExt = fileNameWithExt.substring(0,sepPosition);
    }else{
        fileNameWithOutExt = fileNameWithExt;
    }

    return fileNameWithOutExt;
}
Campa
fuente
0

Qué tal esto:

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);
León
fuente
0

Para devolver un nombre de archivo sin extensión y sin parámetros, utilice lo siguiente:

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

Para devolver un nombre de archivo con extensión sin parámetros use esto:

/** 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 "";
    }
}
Chaiavi
fuente
0

Más allá de todos los métodos avanzados, mi truco simple es 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);
    }
}
Blasanka
fuente
0

Si está utilizando Spring , hay un ayudante para manejar los URI. Aquí está la solución:

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

devolver nuevo archivo (Uri.parse (url) .getPath ()). getName ()

GangrenaGastrit
fuente
-1
create a new file with string image path

    String imagePath;
    File test = new File(imagePath);
    test.getName();
    test.getPath();
    getExtension(test.getName());


    public static String getExtension(String uri) {
            if (uri == null) {
                return null;
            }

            int dot = uri.lastIndexOf(".");
            if (dot >= 0) {
                return uri.substring(dot);
            } else {
                // No extension.
                return "";
            }
        }
Pravin Bhosale
fuente
-1

Tengo el mismo problema con el tuyo. Lo resolví con esto:

var URL = window.location.pathname; // Gets page name
var page = URL.substring(URL.lastIndexOf('/') + 1); 
console.info(page)
Via Marie Inte
fuente
Java no es JavaScript
nathanfranke
-3

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

 }

Espero que esto ayude.

Ricardo Felgueiras
fuente
2
getFile () no hace lo que piensas. Según el documento, en realidad es getPath () + getQuery, lo cual es bastante inútil. java.sun.com/j2se/1.4.2/docs/api/java/net/URL.html#getFile ()
bobince 03 de