Java에서 파일의 Mime 유형 가져 오기


336

대부분의 사람들이 Java의 파일에서 MIME 유형을 가져 오는 방법이 궁금합니다. 지금까지 두 가지 유틸리티를 시도했습니다 : JMimeMagic& Mime-Util.

첫 번째는 메모리 예외를 주었고 두 번째는 스트림을 올바르게 닫지 않습니다. 다른 사람이 올바르게 사용하고 올바르게 작동하는 방법 / 라이브러리가 있는지 궁금합니다.


4
가능한 라이브러리에 좋은 개요에 주어진 rgagnon.com/javadetails/java-0487.html
koppor

나는 대답으로 게시 된 클래스를 사용했습니다 : stackoverflow.com/a/10140531/293280
Joshua Pinter

3
티카가 답이되어야합니다. 아래의 다른 답변은 Tika와의 많은 종속성을 나타내지 만 tika-core에는 아무것도 없습니다.
javamonkey79

@ javamonkey79 TIka를 사용할 때 파일을 보호하고 더 이상 사용할 수 없습니다. String contentType = tika.detect (is)입니다.
Cool Techie

답변:


326

Java 7에서는 이제을 사용할 수 있습니다 Files.probeContentType(path).


62
Files.probeContentType (Path)은 여러 OS에서 버그가 있으며 많은 버그 보고서가 제출되었습니다. 우분투에서 작동하지만 Windows에서 작동하지 않는 소프트웨어에 문제가 있습니다. Windows에서 Files.probeContentType (Path)은 항상 null을 반환하는 것 같습니다. 내 시스템이 아니기 때문에 JRE 또는 Windows 버전을 확인하지 않았습니다. 이 자바 7에 대한 윈도우 7 또는 Oracle JRE와 아마 8이었다
실버

13
나는 OS X 10.9에서 실행 그리고 난 얻을 null밖으로 .xml, .png.xhtml파일. 내가 끔찍한 일을하고 있는지 모르겠지만 오히려 끔찍한 것 같습니다.

36
이에 대한 주요 제한 사항은 파일이 파일 시스템에 존재해야한다는 것입니다. 스트림이나 바이트 배열 등에서는 작동하지 않습니다.
Necreaux

3
이 메서드는 이름에서 확장자를 제거 할 때 MIME 형식을 반환 할 수 없습니다. 이름이 test.mp4 인 경우 예를 들어 "test"로 변경하면 null이 반환됩니다. 또한 영화 확장명을 png로 변경하면 png MIME 형식이 반환됩니다
Sarkhan

10
파일에 확장자가 없거나 잘못된 경우 쓸모가 없습니다.
shmosel

215

운수 나쁘게,

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

URL을 사용하면 파일이 잠기므로 예를 들어 삭제할 수 없으므로 작동하지 않습니다.

그러나 당신은 이것을 가지고 있습니다 :

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

또한 파일 확장을 사용하는 것 이상의 이점을 가지고 있으며 내용을 엿볼 수있는 다음 사항

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

그러나 위의 의견에서 제안한 것처럼 내장 마임 유형 표는 예를 들어 MSWord 및 PDF를 포함하지 않고 상당히 제한적입니다. 따라서 일반화하려면 Mime-Util (파일 확장자와 내용을 모두 사용하는 훌륭한 라이브러리)과 같은 내장 라이브러리를 넘어서야합니다.


8
완벽한 솔루션-많은 도움이되었습니다! 포장 FileInputStream로하는 것은 BufferedInputStream, 그렇지 않으면 - 중요한 부분 guessContentTypeFromStream반환 null(전달 된 InputStream인스턴스 표시를 지원해야한다)
YURIY Nakonechnyy

11
Howerver URLConnection는 인식 할 수있는 컨텐츠 유형이 매우 제한되어 있습니다. 예를 들어 감지 할 수 없습니다 application/pdf.
kpentchev

3
닫을 방법이 없어서 잠긴 상태로 유지됩니다. URLConnection을 연결 해제하면 잠금이 해제됩니다.
Lorne의 후작

1
guessContentTypeFromStream과 guessContentTypeFromName은 mp4를 인식하지 못합니다
Hartmut P.

3
guessContentTypeFromName()기본 $JAVA_HOME/lib/content-types.properties파일을 사용 합니다. 당신은 시스템 속성을 변경하여 자신의 확장 파일을 추가 할 수 있습니다System.setProperty("content.types.user.table","/lib/path/to/your/property/file");
Rasika Perera

50

JAF API는 JDK 6의 일부입니다 javax.activation. 패키지를 보십시오 .

가장 흥미로운 클래스는 javax.activation.MimeType실제 MIME 형식 홀더이며 javax.activation.MimetypesFileTypeMap인스턴스가 파일의 MIME 형식을 문자열로 확인할 수있는 클래스입니다.

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

4
불행히도 getContentType(File)상태에 대한 javadoc으로 : 파일 객체의 MIME 유형을 반환합니다 getContentType(f.getName()). 이 클래스의 구현은을 호출합니다 .
Matyas

3
또한 META-INF / mime.types 파일을 사용하여이 기능을 확장 할 수 있으므로 Java 6을 사용해야하는 경우에 적합합니다. docs.oracle.com/javaee/5/api/javax/activation/…
Chexpir

8
당신은에 의해 새로운 개체를 만드는 건너 뛸 수 있습니다MimetypesFileTypeMap.getDefaultFileTypeMap().getContentType(file)
akostadinov

답변 주셔서 감사합니다. 성공적으로 나를 위해 일하고 있습니다.
Radadiya Nikunj

그러나 여전히 파일 이름을 기준으로 콘텐츠 유형을 반환합니다. 그리고 이것은 사용자가 업로드 한 파일에 특히 위험합니다.
Sergey Ponomarev

47

Apache Tika 를 사용하면 세 줄의 코드 만 필요 합니다 .

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

groovy 콘솔이 있다면이 코드를 붙여 넣어 실행하면됩니다.

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

API는 풍부하고 "무엇이든"구문 분석 할 수 있습니다. tika-core 1.14 기준으로 다음이 있습니다.

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)

자세한 내용 은 apidocs 를 참조하십시오.


1
CSV에는 작동하지 않습니다. wtf? stackoverflow.com/questions/46960231/…
gstackoverflow 17. 24시

1
Tika에 대한 한 가지 나쁜 점은 많은 의존성 팽창입니다. 내 항아리의 크기가 54MB 증가했습니다!
helmy

1
@helmyTika 1.17은 독립형이며 648KB에 불과합니다.

... 또는 new Tika().detect(file.toPath())파일의 내용을 기반으로 탐지하는 것이 아니라 파일의 확장자 기반 탐지를 위해
Lu55

@ Lu55 문서는 여전히 문서 내용을 사용한다고 말합니다. 난 당신이 말은 생각 new Tika().detect(file.getPath())만 파일 확장자를 사용하는,
delucasvb

31

Apache Tikatika-core 에서 스트림 접두사의 매직 마커를 기반으로 한 MIME 유형 감지 기능을 제공합니다. tika-core다른 의존성을 가져 오지 않으므로 현재 유지 관리되지 않는 Mime 유형 감지 유틸리티 만큼 가벼워집니다 .

간단한 코드 예제 (자바 7) 변수를 사용 theInputStream하고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();
}

MediaType.detect (...)는 직접 사용할 수 없습니다 ( TIKA-1120 ). 더 많은 힌트는 https://tika.apache.org/0.10/detection.html 에서 제공됩니다 .


1
+1 또한 Metadata.RESOURCE_NAME_KEY생략 할 수 있습니다 (원래 이름이 없거나 의존 할 수없는 경우).이 경우 일부 경우 (예 : 사무실 문서)에 잘못된 결과가 표시됩니다.
user1516873

파일 이름에 확장자가 없으면 XLSX를 감지하는 데 문제가 있지만 ...이 솔루션은 간단하고 우아합니다.
Oscar Pérez

23

Android 개발자 인 경우 유틸리티 클래스를 사용할 수 있습니다 android.webkit.MimeTypeMap MIME 유형을 파일 확장자에 매핑하거나 그 반대로 매핑 를 .

다음 코드 스 니펫이 도움이 될 수 있습니다.

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

3
"/sdcard/path/to/video.extension"과 같은 로컬 파일 경로로 시도한 경우에도 작동합니다. 로컬 파일이 경로에 공백이 포함되어 있으면 문제는 항상 null을 반환
nmxprime

17

에서 roseindia :

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

7
답변을 다운 투표 한 사람은 의견을 추가하여 나와 다른 사람이 더 나은 답변을 게시하는 방법을 배울 수 있도록하십시오.
AlikElzin-kilaka

3
나는 당신에게 투표하지 않았지만 getFileNameMap은 많은 기본 파일 유형 (예 : 'bmp')에서 작동하지 않습니다. 또한 URLConnection.guessContentTypeFromName 같은 일을 반환
인 Ovidiu Buligan

5
매우 불완전한 기능. Java 7부터 html, pdf 및 jpeg 확장자는 올바른 MIME 유형을 반환하지만 js 및 css는 null을 반환합니다!
djsumdog

'webm'으로 테스트했는데 null이 반환되었습니다.
Henrique Rocha

16

java 5-6 을 사용하는 경우 서보 오픈 소스 제품 의이 유틸리티 클래스 .

이 기능 만 필요합니다

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

컨텐츠의 첫 바이트를 검사하고 파일 확장자가 아닌 해당 컨텐츠를 기반으로 컨텐츠 유형을 리턴합니다.


내가 :) 필요한 간단한, 인기, 그리고 몇 가지 파일 형식 근무
user489041

13

대부분의 사람들이 Java의 파일에서 MIME 유형을 가져 오는 방법이 궁금합니다.

파일 및 바이트 배열에서 내용 유형 (마임 유형)을 결정할 수있는 SimpleMagic Java 패키지를 게시했습니다 . 대부분 ~ Unix OS 구성의 일부인 Unix 파일 (1) 명령 매직 파일을 읽고 실행하도록 설계되었습니다.

아파치 티카를 시도했지만은 거대한 종속성 톤, URLConnection파일의 바이트를 사용하지 않으며,MimetypesFileTypeMap 또한 단지 파일 이름에 보인다.

SimpleMagic을 사용하면 다음과 같은 작업을 수행 할 수 있습니다.

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

1
여러 이미지 파일에서 테스트했습니다. 모두 확장명이 바뀌 었습니다. 멋진 도서관에서 제대로 처리했습니다. 물론 그것의 빛도 :).
saurabheights

1
예, 이것은 잘 작동합니다. 그리고 안드로이드 내에서이 솔루션을 사용해야하는 사람들을 위해 build.gradle 파일에 다음을 간단히 포함시킬 수 있습니다 : compile ( 'com.j256.simplemagic : simplemagic : 1.10')
jkincali

1
이것은 훌륭한 솔루션입니다! 감사!
javydreamercsw

5

5 센트로 칩을 만들려면 :

TL, DR

MimetypesFileTypeMap을 사용 하고 거기에없고 특별히 필요한 mime을 mime.types 파일에 추가합니다.

그리고 지금, 긴 독서 :

우선, MIME 유형 목록은 거대 합니다. https://www.iana.org/assignments/media-types/media-types.xhtml

JDK가 제공하는 표준 기능을 먼저 사용하고 싶습니다. 그래도 작동하지 않으면 다른 것을 찾아 보겠습니다.

파일 확장자에서 파일 유형 결정

1.6 이후로 Java는 위의 답변 중 하나에서 지적한 것처럼 MimetypesFileTypeMap을 가지고 있으며 MIME 유형을 결정하는 가장 간단한 방법입니다.

new MimetypesFileTypeMap().getContentType( fileName );

바닐라 구현에서 이것은별로하지 않습니다 (즉, .html에서는 작동하지만 .png에서는 작동하지 않습니다). 그러나 필요한 컨텐츠 유형을 추가하는 것은 매우 간단합니다.

  1. 프로젝트의 META-INF 폴더에 'mime.types'라는 파일을 만듭니다.
  2. 필요한 모든 MIME 유형에 대한 줄을 추가하고 기본 구현은 제공하지 않습니다 (수백 가지 MIME 유형이 있으며 시간이 지남에 따라 목록이 커짐).

png 및 js 파일의 항목 예는 다음과 같습니다.

image/png png PNG
application/javascript js

mime.types 파일 형식에 대한 자세한 내용은 https://docs.oracle.com/javase/7/docs/api/javax/activation/MimetypesFileTypeMap.html을 참조하십시오.

파일 내용에서 파일 형식 결정

1.7 이후로 Java는 java.nio.file.spi.FileTypeDetector 를 가지고 있는데, 이는 구현 방식으로 파일 유형을 결정하기위한 표준 API를 정의합니다 .

파일의 MIME 유형을 가져 오려면 간단히 파일을 하여 코드에서 수행하십시오.

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

API 정의는 파일 이름 또는 파일 내용 (매직 바이트)에서 파일 마임 유형을 결정하는 기능을 지원합니다. 그래서 probeContentType () 때문에이 API의 구현에서 제공된 Path를 사용하여 실제로 연관된 파일을 열려고 시도하는 경우 메소드에서 IOException이 발생합니다.

다시 바닐라 구현 (JDK와 함께 제공되는 것)은 많이 요구됩니다.

멀리 떨어져있는 은하계의 이상적인 세계에서는이 파일-투-마임 유형 문제를 해결하려는 모든 라이브러리가 단순히 구현됩니다. java.nio.file.spi.FileTypeDetector 것입니다. 선호하는 구현 라이브러리의 jar 클래스 경로에 파일을 넣으면됩니다.

TL, DR 섹션이 필요한 실제 세계에서는 이름 옆에 별이 가장 많은 라이브러리를 찾아서 사용해야합니다. 이 특별한 경우에는 (yet;) 필요하지 않습니다.


3

@Joshua Fox의 첫 번째 방법을 포함하여 여러 가지 방법을 시도했습니다. 그러나 일부는 PDF 파일과 같은 빈번한 mimetype을 인식하지 못하고 다른 파일은 가짜 파일로 신뢰할 수 없었습니다 (확장자가 TIF로 변경된 RAR 파일을 사용해 보았습니다). @Joshua Fox가 피상적으로 말한 것처럼 찾은 해결책은 다음과 같이 MimeUtil2 를 사용하는 것입니다.

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

5
MimeUtil2로 전혀 성공하지 못했습니다. 거의 모든 것이 application / octet-stream으로 돌아 왔습니다. `MimeUtil.registerMimeDetector ( "eu.medsea.mimeutil.detector.MagicMimeMimeDetector")로 초기화 한 후 MimeUtil.getMimeTypes ()를 훨씬 더 성공적으로 사용했습니다. MimeUtil.registerMimeDetector ( "eu.medsea.mimeutil.detector.ExtensionMimeDetector"); MimeUtil.registerMimeDetector ( "eu.medsea.mimeutil.detector.OpendesktopMimeDetector"); `
Brian Pipa

2
작업 솔루션에 감사드립니다. 유틸리티 클래스를 인스턴스화하는 방법에 대한 mime-util 설명서는 명확하지 않습니다. 마침내 그것을 시작하고 실행했지만 클래스 이름 문자열을 실제 클래스로 바꿨습니다. MimeUtil.registerMimeDetector (ExtensionMimeDetector.class.getName ()); String mimeType = MimeUtil.getMostSpecificMimeType (MimeUtil.getMimeTypes (파일 이름)). toString ();
Rob Juurlink

2

파일 업로드에는 2 계층 유효성 검사를 사용하는 것이 좋습니다.

먼저 mimeType을 확인하고 확인할 수 있습니다.

두 번째로 파일의 첫 4 바이트를 16 진수로 변환 한 다음 마법의 숫자와 비교해야합니다. 그러면 파일 유효성 검사를 확인하는 정말 안전한 방법입니다.


2

이것이 내가하는 가장 간단한 방법입니다.

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

최고의 솔루션!
Sherzod

2

서블릿으로 작업 중이고 서블릿 컨텍스트를 사용할 수있는 경우 다음을 사용할 수 있습니다.

getServletContext().getMimeType( fileName );

1
무엇입니까 getServletContext?
e-info128

1

스프링 MultipartFile 파일에서;

org.springframework.web.multipart.MultipartFile

file.getContentType();


0

Linux OS에서 작업하는 경우 명령 행이 있습니다 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 "";
}

그때

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

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

2
이것은 작동하지만 IMO는 코드를 특정 OS에 연결하고 외부 유틸리티가 실행중인 시스템에 있어야하기 때문에 나쁜 습관입니다. 나를 잘못 이해하지 마라. 이 솔루션은 완전히 유효한 솔루션이지만 이식성을
깨뜨립니다

@ToVine : 기록을 위해, 나는 정중하게 동의하지 않을 것입니다. 모든 Java 프로그램이 이식 가능해야하는 것은 아닙니다. 문맥과 프로그래머가 그 결정을하게하십시오. en.wikipedia.org/wiki/Java_Native_Interface
Zahnon

0

다양한 다른 라이브러리를 시도한 후 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);

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

이 메소드 Files.probeContentType (String)은 JDK 버전 1.7부터 사용 가능하며 매우 효과적입니다.
레자 라 히미

감사합니다. 일부 사용자가 투표를 중단 한 이유를 이해할 수 없습니다.)))
Vazgen Torosyan

모든에서, 어쩌면 그들은)) : JDK의 이전 버전이
레자 라 히미

0

MimetypesFileTypeMap (). getContentType (new File ( "filename.ext")) 한 줄만 사용하면됩니다 . 완전한 테스트 코드 (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")));
    }
}

이 코드는 다음과 같은 출력을 생성합니다. text / plain


0
File file = new File(PropertiesReader.FILE_PATH);
MimetypesFileTypeMap fileTypeMap = new MimetypesFileTypeMap();
String mimeType = fileTypeMap.getContentType(file);
URLConnection uconnection = file.toURL().openConnection();
mimeType = uconnection.getContentType();

4
이 코드는 문제를 해결할 수 있지만 설명을 포함하면 게시물의 품질을 향상시키는 데 실제로 도움이됩니다.
Shree

0

나는 다음 코드로 그것을했다.

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;

public class MimeFileType {

    public static void main(String args[]){

        try{
            URL url = new URL ("https://www.url.com.pdf");

            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            connection.setRequestMethod("GET");
            connection.setDoOutput(true);
            InputStream content = (InputStream)connection.getInputStream();
            connection.getHeaderField("Content-Type");

            System.out.println("Content-Type "+ connection.getHeaderField("Content-Type"));

            BufferedReader in = new BufferedReader (new InputStreamReader(content));

        }catch (Exception e){

        }
    }
}

0

아파치 티카.

<!-- https://mvnrepository.com/artifact/org.apache.tika/tika-parsers -->
<dependency>
    <groupId>org.apache.tika</groupId>
    <artifactId>tika-parsers</artifactId>
    <version>1.24</version>
</dependency>

그리고 두 줄의 코드.

Tika tika=new Tika();
tika.detect(inputStream);

아래 스크린 샷

여기에 이미지 설명을 입력하십시오

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.