Pregunta

Me preguntaba cómo la mayoría de las personas obtienen un tipo mime de un archivo en Java.Hasta ahora he probado dos utilidades: JMimeMagic & Mime-Util.

El primero me dio excepciones de memoria, el segundo no cierra sus transmisiones correctamente.Me preguntaba si alguien más tenía un método/biblioteca que usara y funcionara correctamente.

¿Fue útil?

Solución

En Java 7 ahora puedes usar Files.probeContentType(path).

Otros consejos

Desafortunadamente,

mimeType = file.toURL().openConnection().getContentType();

no funciona, ya que este uso de URL deja un archivo bloqueado, de modo que, por ejemplo, no se puede eliminar.

Sin embargo, tienes esto:

mimeType= URLConnection.guessContentTypeFromName(file.getName());

y también el siguiente, que tiene la ventaja de ir más allá del mero uso de la extensión del archivo y echar un vistazo al contenido

InputStream is = new BufferedInputStream(new FileInputStream(file));
mimeType = URLConnection.guessContentTypeFromStream(is);
 //...close stream

Sin embargo, como sugiere el comentario anterior, la tabla incorporada de tipos MIME es bastante limitada y no incluye, por ejemplo, MSWord y PDF.Entonces, si desea generalizar, necesitará ir más allá de las bibliotecas integradas, usando, por ejemplo, Mime-Util (que es una gran biblioteca, que utiliza tanto extensión de archivo como contenido).

La API JAF es parte de JDK 6.Mira a javax.activation paquete.

Las clases más interesantes son javax.activation.MimeType - un titular de tipo MIME real - y javax.activation.MimetypesFileTypeMap - clase cuya instancia puede resolver el tipo MIME como Cadena para un archivo:

String fileName = "/path/to/file";
MimetypesFileTypeMap mimeTypesMap = new MimetypesFileTypeMap();

// only by file name
String mimeType = mimeTypesMap.getContentType(fileName);

// or by actual File instance
File file = new File(fileName);
mimeType = mimeTypesMap.getContentType(file);

Con apache tika solo necesitas tres líneas de código:

File file = new File("/path/to/file");
Tika tika = new Tika();
System.out.println(tika.detect(file));

Si tienes una consola genial, simplemente pega y ejecuta este código para jugar con ella:

@Grab('org.apache.tika:tika-core:1.14')
import org.apache.tika.Tika;

def tika = new Tika()
def file = new File("/path/to/file")
println tika.detect(file)

Tenga en cuenta que sus API son ricas y puede analizar "cualquier cosa".A partir de tika-core 1.14, tienes:

String  detect(byte[] prefix)
String  detect(byte[] prefix, String name)
String  detect(File file)
String  detect(InputStream stream)
String  detect(InputStream stream, Metadata metadata)
String  detect(InputStream stream, String name)
String  detect(Path path)
String  detect(String name)
String  detect(URL url)

Ver los apidocs para más información.

apache tika ofertas en tika-núcleo una detección de tipo mime basada en marcadores mágicos en el prefijo de secuencia. tika-core no recupera otras dependencias, lo que lo hace tan liviano como el que actualmente no se mantiene Utilidad de detección de tipo Mime.

Ejemplo de código simple (Java 7), usando las variables theInputStream y theFileName

try (InputStream is = theInputStream;
        BufferedInputStream bis = new BufferedInputStream(is);) {
    AutoDetectParser parser = new AutoDetectParser();
    Detector detector = parser.getDetector();
    Metadata md = new Metadata();
    md.add(Metadata.RESOURCE_NAME_KEY, theFileName);
    MediaType mediaType = detector.detect(bis, md);
    return mediaType.toString();
}

Tenga en cuenta que MediaType.detect(...) no se puede utilizar directamente (TIKA-1120).Se proporcionan más sugerencias en https://tika.apache.org/0.10/detection.html.

Si eres desarrollador de Android, puedes usar una clase de utilidad android.webkit.MimeTypeMap que asigna tipos MIME a extensiones de archivos y viceversa.

El siguiente fragmento de código puede ayudarle.

private static String getMimeType(String fileUrl) {
    String extension = MimeTypeMap.getFileExtensionFromUrl(fileUrl);
    return MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
}

De rosa india:

FileNameMap fileNameMap = URLConnection.getFileNameMap();
String mimeType = fileNameMap.getContentTypeFor("alert.gif");

Si estás atascado con Java 5-6 entonces esta clase de utilidad de producto de código abierto servoy.

Sólo necesitas esta función

public static String getContentType(byte[] data, String name)

Sondea los primeros bytes del contenido y devuelve los tipos de contenido según ese contenido y no por extensión de archivo.

Me preguntaba cómo la mayoría de las personas obtienen un tipo mime de un archivo en Java.

He publicado mi Magia simple Paquete Java que permite la determinación del tipo de contenido (tipo mime) a partir de archivos y matrices de bytes.Está diseñado para leer y ejecutar los archivos mágicos del comando Unix file(1) que forman parte de la mayoría de las configuraciones del sistema operativo Unix.

Probé Apache Tika pero es enorme con toneladas de dependencias, URLConnection no utiliza los bytes de los archivos, y MimetypesFileTypeMap También solo mira los nombres de los archivos.

Con SimpleMagic puedes hacer algo como:

// create a magic utility using the internal magic file
ContentInfoUtil util = new ContentInfoUtil();
// if you want to use a different config file(s), you can load them by hand:
// ContentInfoUtil util = new ContentInfoUtil("/etc/magic");
...
ContentInfo info = util.findMatch("/tmp/upload.tmp");
// or
ContentInfo info = util.findMatch(inputStream);
// or
ContentInfo info = util.findMatch(contentByteArray);

// null if no match
if (info != null) {
   String mimeType = info.getMimeType();
}

Para aportar mis 5 centavos:

TL,DR

yo suelo MimetypesFileTypeMap y agregue cualquier mime que no esté allí y lo necesite específicamente, en el archivo mime.types.

Y ahora, la lectura larga:

En primer lugar, la lista de tipos MIME es enorme, mira aquí: https://www.iana.org/assignments/media-types/media-types.xhtml

Primero me gusta usar las funciones estándar proporcionadas por JDK y, si eso no funciona, buscaré otra cosa.

Determinar el tipo de archivo a partir de la extensión del archivo

Desde la versión 1.6, Java tiene MimetypesFileTypeMap, como se señala en una de las respuestas anteriores, y es la forma más sencilla de determinar el tipo mime:

new MimetypesFileTypeMap().getContentType( fileName );

En su implementación básica, esto no hace mucho (es decir,funciona para .html pero no para .png).Sin embargo, es muy sencillo agregar cualquier tipo de contenido que puedas necesitar:

  1. Cree un archivo llamado 'mime.types' en la carpeta META-INF de su proyecto
  2. Agregue una línea para cada tipo de mime que necesite y la implementación predeterminada no la proporciona (hay cientos de tipos de mime y la lista crece a medida que pasa el tiempo).

Entradas de ejemplo para archivos png y js serían:

image/png png PNG
application/javascript js

Para el formato de archivo mime.types, consulte más detalles aquí: https://docs.oracle.com/javase/7/docs/api/javax/activation/MimetypesFileTypeMap.html

Determinar el tipo de archivo a partir del contenido del archivo

Desde 1.7, Java tiene java.nio.file.spi.FileTypeDetector, que define una API estándar para determinar un tipo de archivo en implementación de manera específica.

Para obtener el tipo mime de un archivo, simplemente usaría Archivos y haz esto en tu código:

Files.probeContentType(Paths.get("either file name or full path goes here"));

La definición de API proporciona funciones que admiten la determinación del tipo mime de archivo a partir del nombre del archivo o del contenido del archivo (bytes mágicos).Es por eso que sondaContentType() El método arroja IOException, en caso de que una implementación de esta API utilice la ruta proporcionada para intentar abrir el archivo asociado a ella.

De nuevo vainilla implementación de este (el que viene con JDK) deja mucho que desear.

En algún mundo ideal en una galaxia muy, muy lejana, todas estas bibliotecas que intentan resolver este problema de tipo archivo a mime simplemente implementarían java.nio.file.spi.FileTypeDetector, colocaría el archivo jar de la biblioteca de implementación preferida en su classpath y eso sería todo.

En el mundo real, aquel en el que necesitas la sección TL,DR, debes encontrar la biblioteca con más estrellas junto a su nombre y usarla.Para este caso particular, no necesito uno (todavía;)).

Probé varias formas de hacerlo, incluidas las primeras dichas por @Joshua Fox.Pero algunos no reconocen tipos MIME frecuentes como los archivos PDF, y otros no pueden ser confiables con archivos falsos (lo intenté con un archivo RAR con la extensión cambiada a TIF).La solución que encontré, como también lo dice @Joshua Fox de manera superficial, es usar MimeUtil2, como esto:

MimeUtil2 mimeUtil = new MimeUtil2();
mimeUtil.registerMimeDetector("eu.medsea.mimeutil.detector.MagicMimeMimeDetector");
String mimeType = MimeUtil2.getMostSpecificMimeType(mimeUtil.getMimeTypes(file)).toString();

Es mejor utilizar la validación de dos capas para cargar archivos.

Primero puede verificar el tipo mime y validarlo.

En segundo lugar, deberías intentar convertir los primeros 4 bytes de tu archivo a hexadecimal y luego compararlos con los números mágicos.Entonces será una forma realmente segura de comprobar las validaciones de archivos.

en primavera Archivo multiparte archivo;

org.springframework.web.multipart.MultipartFile

file.getContentType();

Esta es la forma más sencilla que encontré para hacer esto:

byte[] byteArray = ...
InputStream is = new BufferedInputStream(new ByteArrayInputStream(byteArray));
String mimeType = URLConnection.guessContentTypeFromStream(is);

Si trabajas en Linux OS, hay una línea de comando. file --mimetype:

String mimetype(file){

   //1. run cmd
   Object cmd=Runtime.getRuntime().exec("file --mime-type "+file);

   //2 get output of cmd , then 
    //3. parse mimetype
    if(output){return output.split(":")[1].trim(); }
    return "";
}

Entonces

mimetype("/home/nyapp.war") //  'application/zip'

mimetype("/var/www/ggg/au.mp3") //  'audio/mp3'

Después de probar varias otras bibliotecas, me decidí por mime-util.

<groupId>eu.medsea.mimeutil</groupId>
      <artifactId>mime-util</artifactId>
      <version>2.1.3</version>
</dependency>

File file = new File("D:/test.tif");
MimeUtil.registerMimeDetector("eu.medsea.mimeutil.detector.MagicMimeMimeDetector");
Collection<?> mimeTypes = MimeUtil.getMimeTypes(file);
System.out.println(mimeTypes);
public String getFileContentType(String fileName) {
    String fileType = "Undetermined";
    final File file = new File(fileName);
    try
    {
        fileType = Files.probeContentType(file.toPath());
    }
    catch (IOException ioException)
    {
        System.out.println(
                "ERROR: Unable to determine file type for " + fileName
                        + " due to exception " + ioException);
    }
    return fileType;
}

Puedes hacerlo con solo una línea: MimetypesFileTypeMap().getContentType(nuevo archivo ("nombre de archivo.ext")).Mira el código de prueba completo (Java 7):

import java.io.File;
import javax.activation.MimetypesFileTypeMap;
public class MimeTest {
    public static void main(String a[]){
         System.out.println(new MimetypesFileTypeMap().getContentType(
           new File("/path/filename.txt")));
    }
}

Este código produce el siguiente resultado: Texto sin formato

File file = new File(PropertiesReader.FILE_PATH);
MimetypesFileTypeMap fileTypeMap = new MimetypesFileTypeMap();
String mimeType = fileTypeMap.getContentType(file);
URLConnection uconnection = file.toURL().openConnection();
mimeType = uconnection.getContentType();
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top