Як визначити тип файлу MIME в android?


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

але коли я його називаю, він повертається до нуля.

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
дякую роботу для мене та інше рішення моєї проблеми: публічна статична String getMimeType (Строковий шлях, контекст контексту) {String extention = path.substring (path.lastIndexOf (".")); String mimeTypeMap = MimeTypeMap.getFileExtensionFromUrl (розширення); String mimeType = MimeTypeMap.getSingleton () .getMimeTypeFromExtension (mimeTypeMap); return mimeType;}
Сушант Бетнагар

13
А якщо файл не має гарного розширення? людина може зробити .mp3, і він містить текст
throrin19

2
Тоді вам потрібно буде фактично відкрити файл і перевірити магічне число (залежно від форматуc) у вхідних даних - це, однак, також передбачає, що особа, яка перейменовує txt-файли в mp3, не просто записала ID3в початок його тексту, щоб ще більше возитися з вами.
Єнс

1
Якщо файл має невідоме розширення. Чи повертається метод */*?

3
Якщо у вас є шлях до файлу як / storage / emulated / 0 / Download / images (4) .jpg, і ви запитаєте mimetype, він повертається до нуля.
Калайзельван

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()зробив трюк.
Раджат Саксена

1
Це, безумовно, найкращий варіант відповіді, але він невдало закінчується, якщо ім'я файлу має спеціальний символ, в моєму випадку - apostrophe! Напр. ім'я файлу = Don't go baby.mp3. PatternMatcherВсередині MimeTypeMap.getFileExtensionFromUrl()не може обробляти ім'я файлу і повертає порожній рядок; null виходить міметиком String!
sud007

Нижче є подібне, але без помилок рішення від I. ShvedenenkoWorked для проблем, які я вказав вище. Але ця відповідь була вказівкою в правильному напрямку.
sud007

цей код повертає null зі String "/ storage / emulated / 0 / dcim / screenshots / screenshot_20190319-123828_ubl digital app.jpg".
Абдул

@Abdul Це тому, що цей шлях не має схеми Урі. Він повинен або починатися з file://або content://.
НВ.

33

Вище рішення MimeTypeMap повернуло нуль у моєму використанні. Це працює і простіше:

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

19
Цей метод також може повернути нуль.
Містер Сміт

Здається, він може повернути нуль чи ні, згідно з URI. Здається, жодне тіло не знає, чому ;-(
Thomas Decaux

10
Якщо носій вибрано з андроїд галереї, TYPE повертається. Якщо вибрано з Менеджера файлів, то повертається нуль.
Рахул Растогі

Я можу позитивно підтвердити те, що сказав Рахул, просто перевірив це, і він має рацію
Кріс

У деяких пристроях, якщо я вибираю зображення з галереї, воно також повертається до нуля
Ghanshyam Nayma

21

Оптимізована версія відповіді Йенса з нульовою безпекою та резервним типом.

@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())
            ?.run { MimeTypeMap.getSingleton().getMimeTypeFromExtension(toLowerCase()) }
            ?: fallback // You might set it to */*
}

це спрацювало. трохи надто багатослівний на мій смак, хоча.
filthy_wizard

Звичайно, це може бути написано коротше. З Котліном, мабуть, лише дві-три лінії, однак лисиця була на нульовій безпеці та toLoverCaseчастині.
Тобіас

@filthy_wizard, додав оптимізовану версію саме для вас ;-)
Tobias

Як на мене, використання методу getPath () замість toString () є більш зрозумілим, і просто шлях з використанням синтаксису доступу властивості kotlin.
Леонід

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 (шлях) для отримання розширення файлу?
петерб

7

Зверніть супер пильну увагу umerk44 «и рішення вище. getMimeTypeFromExtensionвикликає guessMimeTypeTypeFromExtensionі є СЛУЧАЛЬНИЙ ДІЙ. Я провів південь на це, тоді придивився уважніше - getMimeTypeFromExtensionповернеться, NULLякщо ви передасте "JPG", тоді як він поверне "image / jpeg", якщо ви передасте його "jpg".


5

Ось рішення, яке я використовував у своєму додатку для 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;
    }

1
URL? Багато URL не має розширення. Наприклад, ця сторінка не має розширення. Для URL-адреси слід використовувати нову URL-адресу (url) .openConnection (). GetRequestProperty ("Тип вмісту");
barwnikk

5

Іноді відповіді Джеба та Йенса не діють і не повертаються нульовими. У цьому випадку я використовую наступне рішення. Заголовок файлу зазвичай містить підпис типу. Я читаю його і порівнюю з відомими в списку підписів .

/**
 *
 * @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 відео, я використовую 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;
}

Людина, це прибив усі відповіді на цю проблему! У мене було те саме питання з усіма класами Legacy. Випуск був таким же, як ви згадували, MimeTypeMap.getFileExtensionFromUrlповертав порожню рядок для Імен файлів, які мають недійсні символи відповідно до внутрішньої реалізації PatternMatcher. Це працювало для мене повністю! Полюбив це, жодних питань поки що!
sud007

@I. Шведененко String extension = file.getName().split("\\.")[1]також працював, тим самим усуваючи метод getExtension ().
Шаїті уль Хасан

Але річ у тому, що, якщо під час створення файлу використовується неправильне розширення? Чи повинен продовження бути єдиним суддею типу mime?
Шаїті уль Хасан

2

MimeTypeMapможе не розпізнати деякі розширення файлів, такі як flv, 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

Для Android Xamarin (З відповіді @ 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), що працював у цьому випадку.


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

Також повертає нульове значення в моєму випадку шлях

/ зберігання / наслідування / 0 / музика / 01 - Ghost on the Dance Floor.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

Я не розумію, чому MimeTypeMap.getFileExtensionFromUrl()виникають проблеми з spaces та деякими іншими символами, які повертаються "", але я просто написав цей метод, щоб змінити ім'я файлу на визнаний. Це просто гра з Strings. Однак це свого роду працює. За допомогою методу spaceіснуючий у імені файлу s перетворюється на бажаний символ (який тут є "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;
    }
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.