Как определить тип файла MIME в Android? - PullRequest
152 голосов
/ 21 декабря 2011

Предположим, у меня есть полный путь к файлу, например: (/ 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;
}

, но когда я его вызываю, он возвращает ноль.

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

Ответы [ 23 ]

291 голосов
/ 21 декабря 2011

Прежде всего, вы должны подумать о том, чтобы позвонить 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;
}
134 голосов
/ 29 июля 2015

Определить 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;
}
32 голосов
/ 13 января 2013

Приведенное выше решение MimeTypeMap вернуло null при моем использовании. Это работает, и это проще:

Uri uri = Uri.fromFile(file);
ContentResolver cR = context.getContentResolver();
String mime = cR.getType(uri);
16 голосов
/ 07 октября 2016

Оптимизированная версия Дженс ' отвечает с нулевой безопасностью и резервным типом.

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

Бонус: вышеописанные методы как менее подробные Функция расширения Котлина :

fun File.getMimeType(fallback: String = "image/*"): String {
    return MimeTypeMap.getFileExtensionFromUrl(toString())
            ?.apply { MimeTypeMap.getSingleton().getMimeTypeFromExtension(toLowerCase()) }
            ?: fallback // You might set it to */*
}
15 голосов
/ 14 января 2014
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();

    }
6 голосов
/ 19 января 2014

Обратите супер пристальное внимание на umerk44 s решение выше. getMimeTypeFromExtension вызывает guessMimeTypeTypeFromExtension и ЧУВСТВИТЕЛЬНО К СЛУЧАЮ. Я потратил полдня на это, затем присмотрелся - getMimeTypeFromExtension вернет NULL, если вы передадите ему «JPG», тогда как он вернет «image / jpeg», если вы передадите ему «jpg».

5 голосов
/ 01 сентября 2013

Вот решение, которое я использовал в своем приложении для Android:

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;
    }
4 голосов
/ 13 марта 2015

Иногда ответы Джеба и Йенса не работают и возвращают ноль. В этом случае я использую следующее решение. Заголовок файла обычно содержит тип подписи. Я читаю его и сравниваю с известным в списке подписей .

/**
 *
 * @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 .

3 голосов
/ 04 июня 2016

Я пытался использовать стандартные методы для определения типа MIME, но я не могу сохранить расширение файла, используя MimeTypeMap.getFileExtensionFromUrl (uri.getPath ()).Этот метод вернул мне пустую строку.Поэтому я принял нетривиальное решение для сохранения расширения файла.

Вот метод, возвращающий расширение файла

private String getExtention(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 = getExtention(file.getName());
    if (MimeTypeMap.getSingleton().hasExtension(extension)) {
        mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
    }
    return mimeType;
}
2 голосов
/ 21 июня 2017

Для Xamarin Android (Из ответа @ 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;
}
...