안드로이드에서 MIME 유형의 파일을 결정하는 방법은 무엇입니까?


176

(/sdcard/tlogo.png)와 같은 파일의 전체 경로가 있다고 가정하십시오. MIME 유형을 알고 싶습니다.

나는 그것을위한 함수를 만들었다

public static String getMimeType(File file, Context context)    
{
    Uri uri = Uri.fromFile(file);
    ContentResolver cR = context.getContentResolver();
    MimeTypeMap mime = MimeTypeMap.getSingleton();
    String type = mime.getExtensionFromMimeType(cR.getType(uri));
    return type;
}

하지만 내가 전화하면 null을 반환합니다.

File file = new File(filePath);
String fileType=CommonFunctions.getMimeType(file, context);

답변:


323

가장 먼저 다음과 MimeTypeMap#getMimeTypeFromExtension()같이 호출하는 것을 고려해야 합니다.

// url = file path or whatever suitable URL you want.
public static String getMimeType(String url) {
    String type = null;
    String extension = MimeTypeMap.getFileExtensionFromUrl(url);
    if (extension != null) {
        type = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
    }
    return type;
}

4
나에게 고마워하는 일과 내 문제의 또 다른 해결책은 다음과 같습니다. public static String getMimeType (String path, Context context) {String extention = path.substring (path.lastIndexOf ( ".")); String mimeTypeMap = MimeTypeMap.getFileExtensionFromUrl (확대); String mimeType = MimeTypeMap.getSingleton () .getMimeTypeFromExtension (mimeTypeMap); return mimeType;}
Sushant Bhatnagar

13
그리고 파일의 확장자가 좋지 않다면? 사람은 .mp3를 만들 수 있고 텍스트를 포함합니다
throrin19

2
그런 다음 실제로 파일을 열고 리드 인에서 매직 번호 (ofc 형식에 따라 다름)를 확인해야합니다. 그러나 이것은 txt 파일의 이름을 mp3로 바꾸는 사람 ID3이 그의 텍스트의 시작은 당신을 더 엉망으로합니다.
Jens

1
파일의 확장자를 알 수없는 경우 메소드가 리턴 */*합니까?

3
파일 경로가 / storage / emulated / 0 / Download / images (4) .jpg 인 경우 mimetype을 요청하면 null이 반환됩니다.
Kalaiselvan

165

모든 파일의 MIME 유형 감지

public String getMimeType(Uri uri) {           
    String mimeType = null;
    if (uri.getScheme().equals(ContentResolver.SCHEME_CONTENT)) {
        ContentResolver cr = getAppContext().getContentResolver();
        mimeType = cr.getType(uri);
    } else {
        String fileExtension = MimeTypeMap.getFileExtensionFromUrl(uri
                .toString());
        mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(
                fileExtension.toLowerCase());
    }
    return mimeType;
}

5
이것이 정답이어야합니다. toLowerCase()트릭을했다.
Rajat Saxena

1
이것은 지금까지 가장 좋은 대답이지만 파일 이름에 특수 문자가 있으면 비참하게 실패합니다 apostrophe. 예 : 파일 이름 = Don't go baby.mp3. PatternMatcher내부 MimeTypeMap.getFileExtensionFromUrl()파일 이름을 처리하고 빈 문자열을 반환 할 수 없습니다; null은 mimetype String이됩니다!
sud007

I. Shvedenenko위에서 지적한 문제에 대해 Worked 의 유사하지만 오류가없는 솔루션이 있습니다 . 그러나이 답변은 올바른 방향의 포인터였습니다.
sud007

이 코드는 String "/ storage / emulated / 0 / dcim / screenshots / screenshot_20190319-123828_ubl digital app.jpg"와 함께 null을 반환합니다.
Abdul

@Abdul 해당 경로에는 Uri 체계가 없기 때문입니다. file://또는로 시작해야합니다 content://.
HB.

33

위의 MimeTypeMap 솔루션이 내 사용법에서 null을 반환했습니다. 이것은 작동하며 더 쉽습니다.

Uri uri = Uri.fromFile(file);
ContentResolver cR = context.getContentResolver();
String mime = cR.getType(uri);

19
이 메소드는 또한 널을 리턴 할 수 있습니다.
Mister Smith

URI에 따라 null을 반환하거나 반환하지 않는 것 같습니다. 아무도 왜 그런지 알지 못하는 것 같다 ;-(
Thomas Decaux

10
안드로이드 갤러리에서 미디어를 선택하면 TYPE이 반환됩니다. 파일 관리자에서 선택하면 null이 반환됩니다.
Rahul Rastogi

라훌이 말한 것을 긍정적으로 확인할 수 있습니다. 그냥 시험해
Chris

일부 장치에서 나는 또한 반환 널 갤러리에서 이미지를 선택하면
Ghanshyam Nayma

21

null 안전 및 대체 유형 으로 Jens 응답 의 최적화 된 버전 .

@NonNull
static String getMimeType(@NonNull File file) {
    String type = null;
    final String url = file.toString();
    final String extension = MimeTypeMap.getFileExtensionFromUrl(url);
    if (extension != null) {
        type = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension.toLowerCase());
    }
    if (type == null) {
        type = "image/*"; // fallback type. You might set it to */*
    }
    return type;
}

중요 : getFileExtensionFromUrl ()은 소문자 에서만 작동합니다 !


업데이트 (19.03.2018)

보너스 : 덜 장황한 Kotlin 확장 기능 으로 위의 방법 :

fun File.getMimeType(fallback: String = "image/*"): String {
    return MimeTypeMap.getFileExtensionFromUrl(toString())
            ?.run { MimeTypeMap.getSingleton().getMimeTypeFromExtension(toLowerCase()) }
            ?: fallback // You might set it to */*
}

이것은 효과가 있었다. 그래도 내 취향에 대해 지나치게 장황합니다.
filthy_wizard

물론 이것은 더 짧은 방식으로 작성 될 수 있습니다. Kotlin을 사용하면 아마도 두 세 줄 밖에되지 않지만 여우는 안전하지 않은 toLoverCase부분에있었습니다.
Tobias

@filthy_wizard, 당신만을위한 최적화 된 버전을 추가했습니다 ;-)
Tobias

나에 관해서는 toString () 대신 getPath () 메소드를 사용하는 것이 더 명확하며 kotlin 속성 액세스 구문을 사용하는 경로입니다.
Leonid

15
File file = new File(path, name);

    MimeTypeMap mime = MimeTypeMap.getSingleton();
    int index = file.getName().lastIndexOf('.')+1;
    String ext = file.getName().substring(index).toLowerCase();
    String type = mime.getMimeTypeFromExtension(ext);

    intent.setDataAndType(Uri.fromFile(file), type);
    try
    {
      context.startActivity(intent);
    }
    catch(ActivityNotFoundException ex)
    {
        ex.printStackTrace();

    }

1
나를 위해 완벽하게 작동합니다! 그러나 FilenameUtils.getExetension (path)을 사용하여 파일 확장자를 얻는 방법은 어떻습니까?
peterb

7

위 의 umerk44 솔루션에 세심한주의를 기울이 십시오 . CASE SENSITIVE를 getMimeTypeFromExtension호출합니다 guessMimeTypeTypeFromExtension. 나는이 다음 면밀한 관찰을했다에 오후를 보냈다 - getMimeTypeFromExtension반환 NULL당신이 "JPG"당신이 "JPG"를 전달할 경우는 "이미지 / JPEG"를 반환하는 반면 그것을 전달하는 경우.


5

내 안드로이드 앱에서 사용한 솔루션은 다음과 같습니다.

public static String getMimeType(String url)
    {
        String extension = url.substring(url.lastIndexOf("."));
        String mimeTypeMap = MimeTypeMap.getFileExtensionFromUrl(extension);
        String mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(mimeTypeMap);
        return mimeType;
    }

1
URL? 많은 URL에는 확장자가 없습니다. 예를 들어이 페이지에는 확장명이 없습니다. URL의 경우 new URL (url) .openConnection (). getRequestProperty ( "Content-type")을 사용해야합니다.
barwnikk

5

때로는 Jeb와 Jens의 답변이 작동하지 않고 null을 반환합니다. 이 경우 다음 해결책을 사용합니다. 파일 헤드는 일반적으로 형식 서명을 포함합니다. 나는 그것을 읽고 서명 목록에 알려진 것과 비교 합니다 .

/**
 *
 * @param is InputStream on start of file. Otherwise signature can not be defined.
 * @return int id of signature or -1, if unknown signature was found. See SIGNATURE_ID_(type) constants to
 *      identify signature by its id.
 * @throws IOException in cases of read errors.
 */
public static int getSignatureIdFromHeader(InputStream is) throws IOException {
    // read signature from head of source and compare with known signatures
    int signatureId = -1;
    int sigCount = SIGNATURES.length;
    int[] byteArray = new int[MAX_SIGNATURE_LENGTH];
    StringBuilder builder = new StringBuilder();
    for (int i = 0; i < MAX_SIGNATURE_LENGTH; i++) {
        byteArray[i] = is.read();
        builder.append(Integer.toHexString(byteArray[i]));
    }
    if (DEBUG) {
        Log.d(TAG, "head bytes=" + builder.toString());
    }
    for (int i = 0; i < MAX_SIGNATURE_LENGTH; i++) {

        // check each bytes with known signatures
        int bytes = byteArray[i];
        int lastSigId = -1;
        int coincidences = 0;

        for (int j = 0; j < sigCount; j++) {
            int[] sig = SIGNATURES[j];

            if (DEBUG) {
                Log.d(TAG, "compare" + i + ": " + Integer.toHexString(bytes) + " with " + sig[i]);
            }
            if (bytes == sig[i]) {
                lastSigId = j;
                coincidences++;
            }
        }

        // signature is unknown
        if (coincidences == 0) {
            break;
        }
        // if first bytes of signature is known we check signature for full coincidence
        if (coincidences == 1) {
            int[] sig = SIGNATURES[lastSigId];
            int sigLength = sig.length;
            boolean isSigKnown = true;
            for (; i < MAX_SIGNATURE_LENGTH && i < sigLength; i++) {
                bytes = byteArray[i];
                if (bytes != sig[i]) {
                    isSigKnown = false;
                    break;
                }
            }
            if (isSigKnown) {
                signatureId = lastSigId;
            }
            break;
        }
    }
    return signatureId;
}

signatureId서명 배열의 서명 색인입니다. 예를 들어

private static final int[] SIGNATURE_PNG = hexStringToIntArray("89504E470D0A1A0A");
private static final int[] SIGNATURE_JPEG = hexStringToIntArray("FFD8FF");
private static final int[] SIGNATURE_GIF = hexStringToIntArray("474946");

public static final int SIGNATURE_ID_JPEG = 0;
public static final int SIGNATURE_ID_PNG = 1;
public static final int SIGNATURE_ID_GIF = 2;
private static final int[][] SIGNATURES = new int[3][];

static {
    SIGNATURES[SIGNATURE_ID_JPEG] = SIGNATURE_JPEG;
    SIGNATURES[SIGNATURE_ID_PNG] = SIGNATURE_PNG;
    SIGNATURES[SIGNATURE_ID_GIF] = SIGNATURE_GIF;
}

이제 파일의 URI가 없어도 파일 형식이 있습니다. 다음으로 파일 유형별로 MIME 유형을 얻습니다. 얻을 수있는 MIME 유형을 모르는 경우이 표 에서 적절한 것을 찾을 수 있습니다 .

많은 파일 형식에서 작동합니다. 그러나 비디오의 경우 MIME 유형을 얻으려면 비디오 코덱을 알아야하므로 작동하지 않습니다. 비디오의 MIME 유형을 얻으려면 MediaMetadataRetriever를 사용 합니다.


4

표준 방법을 사용하여 MIME 유형을 확인하려고했지만를 사용하여 파일 확장자를 유지할 수 없습니다 MimeTypeMap.getFileExtensionFromUrl(uri.getPath()). 이 메소드는 빈 문자열을 반환했습니다. 그래서 파일 확장자를 유지하기 위해 사소한 해결책을 만들었습니다.

파일 확장자를 반환하는 방법은 다음과 같습니다.

private String getExtension(String fileName){
    char[] arrayOfFilename = fileName.toCharArray();
    for(int i = arrayOfFilename.length-1; i > 0; i--){
        if(arrayOfFilename[i] == '.'){
            return fileName.substring(i+1, fileName.length());
        }
    }
    return "";
}

파일 확장자를 유지하면 다음과 같이 MIME 유형을 얻을 수 있습니다.

public String getMimeType(File file) {
    String mimeType = "";
    String extension = getExtension(file.getName());
    if (MimeTypeMap.getSingleton().hasExtension(extension)) {
        mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
    }
    return mimeType;
}

이 문제에 대해 여기에 게시 된 모든 답변을 수정했습니다. 모든 레거시 클래스에서 동일한 문제가 발생했습니다. 문제는 언급 한 것과 같 MimeTypeMap.getFileExtensionFromUrl으며 파일의 내부 구현에 따라 유효하지 않은 문자가있는 파일 이름에 대해 빈 문자열을 반환했습니다 PatternMatcher. 이것은 나를 위해 완전히 효과가있었습니다! 지금까지 문제가 없었습니다.
sud007

@나는. Shvedenenko String extension = file.getName().split("\\.")[1]도 작동하여 getExtension () 메소드를 제거했습니다.
Shahood ul Hassan

그러나 문제는 파일을 만드는 동안 잘못된 확장명을 사용하면 어떻게 될까요? 확장은 MIME 유형의 유일한 판사 여야합니까?
Shahood ul Hassan

2

MimeTypeMapflv, mpeg, 3gpp, cpp와 같은 일부 파일 확장자를 인식하지 못할 수 있습니다. 따라서 코드를 유지 관리하기 위해 MimeTypeMap을 확장하는 방법을 고려해야합니다. 다음은 그러한 예입니다.

http://grepcode.com/file/repo1.maven.org/maven2/com.google.okhttp/okhttp/20120626/libcore/net/MimeUtils.java#MimeUtils

또한, 여기에 MIME 유형의 전체 목록이 있습니다

http : //www.sitepoint.com/web-foundations/mime-types-complete-list/


2

대한 자 마린 안드로이드 (에서 위의 HoaLe의 대답 @)

public String getMimeType(Uri uri) {
    String mimeType = null;
    if (uri.Scheme.Equals(ContentResolver.SchemeContent))
    {
        ContentResolver cr = Application.Context.ContentResolver;
        mimeType = cr.GetType(uri);
    }
    else
    {
        String fileExtension = MimeTypeMap.GetFileExtensionFromUrl(uri.ToString());
        mimeType = MimeTypeMap.Singleton.GetMimeTypeFromExtension(
        fileExtension.ToLower());
    }
    return mimeType;
}

1
get file object....
File file = new File(filePath);

then....pass as a parameter to...

getMimeType(file);

...here is 


public String getMimeType(File file) {
        String mimetype = MimeTypeMap.getSingleton().getMimeTypeFromExtension(MimeTypeMap.getFileExtensionFromUrl(Uri.fromFile(file).toString()).toLowerCase());
        if (mimetype == null) {
            return "*/*";
        }
        return mimetype;///return the mimeType
    }

1

자산 / 파일에서 (MimeTypeMap에서 누락 된 경우는 거의 없음)

private String getMimeType(String path) {
    if (null == path) return "*/*";

    String extension = path;
    int lastDot = extension.lastIndexOf('.');
    if (lastDot != -1) {
        extension = extension.substring(lastDot + 1);
    }

    // Convert the URI string to lower case to ensure compatibility with MimeTypeMap (see CB-2185).
    extension = extension.toLowerCase(Locale.getDefault());
    if (extension.equals("3ga")) {
        return "audio/3gpp";
    } else if (extension.equals("js")) {
        return "text/javascript";
    } else if (extension.equals("woff")) {
        return "application/x-font-woff";
    } else {
        // TODO
        // anyting missing from the map (http://www.sitepoint.com/web-foundations/mime-types-complete-list/)
        // reference: http://grepcode.com/file/repo1.maven.org/maven2/com.google.okhttp/okhttp/20120626/libcore/net/MimeUtils.java#MimeUtils
    }

    return MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
}

ContentResolver를 사용하는 동안

contentResolver.getType(uri)

http / https가 요청하는 동안

    try {
        HttpURLConnection conn = httpClient.open(new URL(uri.toString()));
        conn.setDoInput(false);
        conn.setRequestMethod("HEAD");
        return conn.getHeaderField("Content-Type");
    } catch (IOException e) {
    }

1
// This will return the mimeType. 
// for eg. xyz.png it will return image/png. 
// here uri is the file that we were picked using intent from ext/internal storage.
private String getMimeType(Uri uri) {
   // This class provides applications access to the content model.  
   ContentResolver contentResolver = getContentResolver();

   // getType(Uri url)-Return the MIME type of the given content URL. 
   return contentResolver.getType(uri);
}

설명을 제공해주세요. 초기 독자가 자신의 코드를 조정하고 추가 독자가 귀하의 답변에서 최대한의 가치를 얻도록 도와줍니다.
Aurélien B

답변 주셔서 감사합니다. 설명과 함께 편집합니다.
iamdhariot

1

나는 비슷한 문제에 직면했다. 지금까지 나는 이름이 다르면 결과가 다를 수 있다는 것을 알고 마침내이 솔루션에 왔습니다.

public String getMimeType(String filePath) {
    String type = null;
    String extension = null;
    int i = filePath.lastIndexOf('.');
    if (i > 0)
        extension = filePath.substring(i+1);
    if (extension != null)
        type = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
    return type;
}  

0

위의 솔루션은 .rar 파일의 경우 URLConnection.guessContentTypeFromName (url)을 사용하여 null을 반환했습니다.


0

로컬 파일에서 MIME :

String url = file.getAbsolutePath();
FileNameMap fileNameMap = URLConnection.getFileNameMap();
String mime = fileNameMap.getContentTypeFor("file://"+url);

0

같은 : 1 당신은 파일의 확장자를 얻을 수있는 여러 선택이 String filename = uri.getLastPathSegment();이 참조 링크를

2-이 코드도 사용할 수 있습니다

 filePath .substring(filePath.lastIndexOf(".")+1);

그러나 이것은 좋지 않습니다. 3- 파일 URI가있는 경우이 코드를 사용하십시오

String[] projection = { MediaStore.MediaColumns.DATA,
MediaStore.MediaColumns.MIME_TYPE };

4-URL이 있으면이 코드를 사용하십시오.

 public static String getMimeType(String url) {
String type = null;
String extension = MimeTypeMap.getFileExtensionFromUrl(url);
if (extension != null) { 


  type = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
    }

return type;
}

코드를 즐기십시오 :)


0
// new processing the mime type out of Uri which may return null in some cases
String mimeType = getContentResolver().getType(uri);
// old processing the mime type out of path using the extension part if new way returned null
if (mimeType == null){mimeType URLConnection.guessContentTypeFromName(path);}

0
public static String getFileType(Uri file)
{
    try
    {
        if (file.getScheme().equals(ContentResolver.SCHEME_CONTENT))
            return subStringFromLastMark(SystemMaster.getContentResolver().getType(file), "/");
        else
            return MimeTypeMap.getFileExtensionFromUrl(file.toString()).toLowerCase();
    }
    catch(Exception e)
    {
        return null;
    }
}

public static String getMimeType(Uri file)
{
    try
    {
        return MimeTypeMap.getSingleton().getMimeTypeFromExtension(getFileType(file));
    }
    catch(Exception e)
    {
        return null;
    }
}

public static String subStringFromLastMark(String str,String mark)
{
    int l = str.lastIndexOf(mark);
    int end = str.length();
    if(l == -1)
        return str;

    return str.substring(l + 1, end);
}

0

내 경우 경로에서 null 값을 반환했습니다.

/ storage / emulated / 0 / Music / 01-댄스 플로어의 유령 .mp3

사용 해결 방법으로

val url = inUrl.replace ( "", "")

그래서 방법은

@JvmStatic
    fun getMimeType(inUrl: String?): String {
        if (inUrl == null) return ""

        val url = inUrl.replace(" ","")
        var type: String? = null

        val extension = MimeTypeMap.getFileExtensionFromUrl(url)
        if (extension != null) {
            type = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension.toLowerCase())
        }

        if(type ==null){
            val cR = WifiTalkie.getApplicationContext().contentResolver
            type = cR.getType(Uri.parse(url))
        }

        if (type == null) {
            type = "*/*" // fallback method_type. You might set it to */*
        }
        return type
    }

결과적으로 성공 결과를 반환합니다.

오디오 / mpeg

그것이 누군가를 돕기를 바랍니다.


0

완벽한 답변은 없습니다. 다음은 모든 최상위 답변의 최상의 요소를 결합한 답변입니다.

public final class FileUtil {

    // By default, Android doesn't provide support for JSON
    public static final String MIME_TYPE_JSON = "application/json";

    @Nullable
    public static String getMimeType(@NonNull Context context, @NonNull Uri uri) {

        String mimeType = null;
        if (uri.getScheme().equals(ContentResolver.SCHEME_CONTENT)) {
            ContentResolver cr = context.getContentResolver();
            mimeType = cr.getType(uri);
        } else {
            String fileExtension = getExtension(uri.toString());

            if(fileExtension == null){
                return null;
            }

            mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(
                    fileExtension.toLowerCase());

            if(mimeType == null){
                // Handle the misc file extensions
                return handleMiscFileExtensions(fileExtension);
            }
        }
        return mimeType;
    }

    @Nullable
    private static String getExtension(@Nullable String fileName){

        if(fileName == null || TextUtils.isEmpty(fileName)){
            return null;
        }

        char[] arrayOfFilename = fileName.toCharArray();
        for(int i = arrayOfFilename.length-1; i > 0; i--){
            if(arrayOfFilename[i] == '.'){
                return fileName.substring(i+1, fileName.length());
            }
        }
        return null;
    }

    @Nullable
    private static String handleMiscFileExtensions(@NonNull String extension){

        if(extension.equals("json")){
            return MIME_TYPE_JSON;
        }
        else{
            return null;
        }
    }
}

0
Intent myIntent = new Intent(android.content.Intent.ACTION_VIEW);
                        File file = new File(filePatch); 
                        Uri uris = Uri.fromFile(file);
                        String mimetype = null;
                        if 
(uris.getScheme().equals(ContentResolver.SCHEME_CONTENT)) {
                            ContentResolver cr = 
getApplicationContext().getContentResolver();
                            mimetype = cr.getType(uris);
                        } else {
                            String fileExtension = 
MimeTypeMap.getFileExtensionFromUrl(uris.toString());
mimetype =  MimeTypeMap.getSingleton().getMimeTypeFromExtension(fileExtension.toLowerCase());
                        }


0

나는 s 및 다른 문자에 MimeTypeMap.getFileExtensionFromUrl()문제가있는 이유 를 알지 못하지만 space을 반환 ""하지만 파일 이름을 허용 가능한 이름으로 변경하기 위해이 방법을 작성했습니다. 그냥 Strings 와 놀고 있습니다 . 그러나 그것은 일종의 작동합니다. 이 방법을 통해, space파일 이름에 존재하는 파일은 via를 통해 원하는 문자 (여기서는 "x") replaceAll(" ", "x")로 바뀌고 다른 부적절한 문자는 via를 통해 적합한 문자로 바뀝니다 URLEncoder. 따라서 사용법 (질문에 표시된 코드와 선택한 답변에 따라)은 다음과 같아야 getMimeType(reviseUrl(url))합니다.

private String reviseUrl(String url) {

        String revisedUrl = "";
        int fileNameBeginning = url.lastIndexOf("/");
        int fileNameEnding = url.lastIndexOf(".");

        String cutFileNameFromUrl = url.substring(fileNameBeginning + 1, fileNameEnding).replaceAll(" ", "x");

        revisedUrl = url.
                substring(0, fileNameBeginning + 1) +
                java.net.URLEncoder.encode(cutFileNameFromUrl) +
                url.substring(fileNameEnding, url.length());

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