Jak określić typ pliku MIME w systemie Android?


176

Załóżmy, że mam pełną ścieżkę do pliku, taką jak: (/ sdcard / tlogo.png). Chcę poznać jego typ mime.

Stworzyłem dla niego funkcję

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

ale kiedy to nazywam, zwraca wartość null.

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

Odpowiedzi:


323

Przede wszystkim powinieneś rozważyć zadzwonienie w MimeTypeMap#getMimeTypeFromExtension()ten sposób:

// 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
dzięki za pracę dla mnie i innym rozwiązaniem mojego problemu jest: public static String getMimeType (ścieżka ciągu, kontekst kontekstu) {String extention = path.substring (path.lastIndexOf (".")); String mimeTypeMap = MimeTypeMap.getFileExtensionFromUrl (extention); String mimeType = MimeTypeMap.getSingleton () .getMimeTypeFromExtension (mimeTypeMap); return mimeType;}
Sushant Bhatnagar

13
A jeśli plik nie ma dobrego rozszerzenia? osoba może stworzyć .mp3 i zawiera tekst
throrin19

2
Następnie musiałbyś faktycznie otworzyć plik i sprawdzić magiczną liczbę (w zależności od formatu c) na wejściu - zakłada to jednak również, że osoba zmieniająca nazwy plików txt na mp3 nie pisała po prostu ID3w początek jego tekstu, by jeszcze bardziej zepsuć z Tobą.
Jens,

1
Jeśli plik ma nieznane rozszerzenie. Czy metoda zwraca */*?

3
Jeśli masz ścieżkę do pliku / storage / emulated / 0 / Download / images (4) .jpg i poprosisz o podanie typu MIME, zwraca wartość null.
Kalaiselvan

165

Wykryj typ MIME dowolnego pliku

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
To powinna być prawidłowa odpowiedź. toLowerCase()załatwił sprawę.
Rajat Saxena

1
To zdecydowanie najlepsza odpowiedź, ale kończy się to żałośnie, jeśli nazwa pliku ma znak specjalny, w moim przypadku apostrophe! Na przykład. nazwa pliku = Don't go baby.mp3. PatternMatcherWewnątrz MimeTypeMap.getFileExtensionFromUrl()nie może obsłużyć nazwę pliku i zwraca pusty ciąg; null jest ciągiem typu MIME!
sud007

Istnieje podobne, ale bezbłędne rozwiązanie poniżej autorstwa I. ShvedenenkoWorked dla problemów, które wskazałem powyżej. Ale ta odpowiedź była wskazówką we właściwym kierunku.
sud007

ten kod zwraca wartość null z ciągiem „/ storage / emulated / 0 / dcim / screenshots / screenshot_20190319-123828_ubl digital app.jpg”.
Abdul

@Abdul Dzieje się tak, ponieważ ta ścieżka nie ma schematu Uri. Powinien zaczynać się od file://lub content://.
HB.

33

Powyższe rozwiązanie MimeTypeMap zwróciło wartość null w moim użyciu. To działa i jest łatwiejsze:

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

19
Ta metoda może również zwrócić wartość null.
Mister Smith

Wygląda na to, że może zwrócić wartość null lub nie, zgodnie z identyfikatorem URI. Wydaje się, że nikt nie wie dlaczego ;-(
Thomas Decaux

10
Jeśli nośnik zostanie wybrany z galerii Androida, zwracany jest TYPE. Jeśli wybrano z Menedżera plików, zwracana jest wartość null.
Rahul Rastogi

Mogę pozytywnie potwierdzić to, co powiedział Rahul, właśnie to przetestowałem i ma rację
Chris

W niektórych urządzeniach gdybym wybrać obraz z galerii również to wraca NULL
Ghanshyam Nayma

21

Zoptymalizowana wersja odpowiedzi Jensa z typem zerowym i awaryjnym.

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

Ważne : getFileExtensionFromUrl () działa tylko z małymi literami !


Aktualizacja (19.03.2018)

Bonus: powyższe metody jako mniej szczegółowa funkcja rozszerzenia Kotlin :

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

to zadziałało. trochę zbyt gadatliwe, jak na mój gust.
filthy_wizard

Oczywiście może to być krótsze. Z Kotlinem prawdopodobnie tylko dwie lub trzy linie, jednak lis był na zerowym bezpieczeństwie i toLoverCaseczęściowo.
Tobias

@filthy_wizard, dodano zoptymalizowaną wersję specjalnie dla Ciebie ;-)
Tobias

Jak dla mnie użycie metody getPath () zamiast toString () jest bardziej przejrzyste i wystarczy ścieżka używając składni dostępu do właściwości 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
U mnie działa idealnie! Ale co powiesz na użycie pliku FilenameUtils.getExetension (ścieżka), aby uzyskać rozszerzenie pliku?
peterb

7

Płacić bardzo baczną uwagę na umerk44 „s rozwiązania powyżej. getMimeTypeFromExtensionwywołuje guessMimeTypeTypeFromExtensioni rozróżnia wielkość liter. Spędziłem nad tym popołudnie, a potem przyjrzałem się bliżej - getMimeTypeFromExtensionwrócę, NULLjeśli podasz "JPG", a zwróci "image / jpeg", jeśli podasz "jpg".


5

Oto rozwiązanie, którego użyłem w mojej aplikacji na Androida:

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? Wiele adresów URL nie ma rozszerzenia. Na przykład ta strona nie ma rozszerzenia. W przypadku adresu URL należy użyć nowego adresu URL (url) .openConnection (). GetRequestProperty ("Content-type");
barwnikk

5

Czasami odpowiedzi Jeba i Jensa nie działają i zwracają zero. W tym przypadku korzystam z rozwiązania follow. Nagłówek pliku zwykle zawiera sygnaturę typu. Przeczytałem i porównuję ze znanymi na liście podpisów .

/**
 *
 * @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;
}

signatureIdjest indeksem podpisu w tablicy podpisów. Na przykład,

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

Teraz mam typ pliku, nawet jeśli nie ma identyfikatora URI pliku. Następnie otrzymuję typ MIME według typu pliku. Jeśli nie wiesz, jaki typ MIME uzyskać, możesz znaleźć odpowiedni w tej tabeli .

Działa dla wielu typów plików. Ale w przypadku wideo to nie działa, ponieważ potrzebujesz znanego kodeka wideo, aby uzyskać typ MIME. Aby uzyskać typ MIME wideo, używam MediaMetadataRetriever .


4

Próbowałem użyć standardowych metod do określenia typu MIME, ale nie mogę zachować rozszerzenia pliku za pomocą MimeTypeMap.getFileExtensionFromUrl(uri.getPath()). Ta metoda zwróciła mi pusty ciąg. Zrobiłem więc nietrywialne rozwiązanie, aby zachować rozszerzenie pliku.

Oto metoda zwracająca rozszerzenie pliku:

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

Zachowując rozszerzenie pliku, można uzyskać typ MIME, jak poniżej:

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

Człowieku, to przybiło wszystkie odpowiedzi zamieszczone tutaj na ten problem! Miałem ten sam problem ze wszystkimi klasami Legacy. Problem był taki sam, jak wspomniałeś, MimeTypeMap.getFileExtensionFromUrlzwrócił pusty ciąg dla nazw plików, które zawierają nieprawidłowe znaki zgodnie z wewnętrzną implementacją pliku PatternMatcher. To zadziałało dla mnie całkowicie! Uwielbiałem to, do tej pory żadnych problemów!
sud007

@JA. Shvedenenko String extension = file.getName().split("\\.")[1]również działałby, eliminując w ten sposób metodę getExtension ().
Shahood ul Hassan

Ale chodzi o to, co się stanie, jeśli podczas tworzenia pliku zostanie użyte niewłaściwe rozszerzenie? Czy rozszerzenie powinno być jedynym sędzią typu pantomimy?
Shahood ul Hassan


2

Dla platformy Xamarin Android (powyższa odpowiedź z @ 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

Podczas gdy z zasobu / pliku (zwróć uwagę, że brakuje kilku przypadków w 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);
}

Podczas korzystania z ContentResolver

contentResolver.getType(uri)

Podczas żądania 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);
}

Proszę podać wyjaśnienie. Pomoże to początkowemu czytelnikowi dostosować swój kod i dalszym czytelnikom, aby uzyskać jak największą wartość z Twojej odpowiedzi.
Aurélien B

Dzięki za twoją odpowiedź. Edytuję to z wyjaśnieniem.
iamdhariot

1

Miałem podobny problem. Na razie wiem, że wynik może się różnić dla różnych nazw, więc w końcu doszedłem do tego rozwiązania.

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

Powyższe rozwiązanie zwróciło wartość null w przypadku pliku .rar, w tym przypadku zadziałało użycie adresu URLConnection.guessContentTypeFromName (url).


0

mime z pliku lokalnego:

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

0

masz wielokrotny wybór, aby uzyskać rozszerzenie pliku: jak: 1- String filename = uri.getLastPathSegment();Zobacz ten link

2-możesz również użyć tego kodu

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

ale to nie jest dobra aprocha. 3 - jeśli masz URI pliku, użyj tego kodu

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

4-jeśli masz adres URL, użyj tego kodu:

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


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

return type;
}

miłego kodu :)


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

Zwrócił również wartość null w mojej ścieżce sprawy

/ storage / emulated / 0 / Music / 01 - Ghost on the Dance Floor.mp3

jako obejście użycia

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

tak wygląda metoda

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

w rezultacie zwraca wynik sukcesu:

audio / mpeg

Mam nadzieję, że to pomoże każdemu


0

Żadna z odpowiedzi tutaj nie jest idealna. Oto odpowiedź łącząca najlepsze elementy ze wszystkich najlepszych odpowiedzi:

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

Nie zdaję sobie sprawy, dlaczego MimeTypeMap.getFileExtensionFromUrl()ma problemy z spacesi kilkoma innymi znakami, które powracają "", ale właśnie napisałem tę metodę, aby zmienić nazwę pliku na dopuszczalną. To tylko zabawa z Strings. Jednak to trochę działa. W ten sposób spaceznaki występujące w nazwie pliku są zamieniane na pożądany znak (tutaj jest to „x”), replaceAll(" ", "x")a inne nieodpowiednie znaki są zamieniane na odpowiedni znak za pomocą URLEncoder. więc użycie (zgodnie z kodami przedstawionymi w pytaniu i wybraną odpowiedzią) powinno być jakoś 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;
    }
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.