Comment déterminer le type de fichier MIME dans Android?

176

Supposons que j'ai un chemin complet de fichier comme: (/ sdcard / tlogo.png). Je veux connaître son type de mime.

J'ai créé une fonction pour cela

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

mais quand je l'appelle, il renvoie null.

File file = new File(filePath);
String fileType=CommonFunctions.getMimeType(file, context);
Sushant Bhatnagar
la source

Réponses:

323

Tout d'abord, vous devriez envisager d'appeler MimeTypeMap#getMimeTypeFromExtension(), comme ceci:

// 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;
}
Jens
la source
4
merci de travailler pour moi et une autre solution à mon problème est: public static String getMimeType (String path, Context context) {String extention = path.substring (path.lastIndexOf (".")); String mimeTypeMap = MimeTypeMap.getFileExtensionFromUrl (extention); Chaîne mimeType = MimeTypeMap.getSingleton () .getMimeTypeFromExtension (mimeTypeMap); return mimeType;}
Sushant Bhatnagar
13
Et si le fichier n'a pas la bonne extension? une personne peut faire un .mp3 et il contient du texte
throrin19
2
Ensuite, vous devez ouvrir le fichier et vérifier le nombre magique (en fonction du format ofc) dans l'introduction - cela, cependant, suppose également que la personne qui a renommé les fichiers txt en mp3 n'a pas simplement écrit ID3dans le début de son texte pour vous embêter encore plus.
Jens
1
Si le fichier a une extension inconnue. La méthode retourne- */*t-elle?
3
Si votre chemin de fichier est / storage / emulated / 0 / Download / images (4) .jpg et que vous demandez le type MIME, il renvoie null.
Kalaiselvan
165

Détecter le type mime de n'importe quel fichier

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;
}
Hoa Le
la source
5
Cela devrait être la bonne réponse. toLowerCase()a fait l'affaire.
Rajat Saxena
1
C'est de loin la meilleure réponse mais elle échoue lamentablement si le nom du fichier a un caractère spécial, dans mon cas un apostrophe! Par exemple. nom de fichier = Don't go baby.mp3. L' PatternMatcherintérieur MimeTypeMap.getFileExtensionFromUrl()ne peut pas gérer le nom du fichier et renvoie une chaîne vide; null est la chaîne de type mime!
sud007
Il existe une solution similaire mais sans erreur ci-dessous par I. ShvedenenkoWorked pour les problèmes que j'ai signalés ci-dessus. Mais cette réponse était un indicateur dans la bonne direction.
sud007
ce code renvoie null avec la chaîne "/ storage / emulated / 0 / dcim / screenshots / screenshot_20190319-123828_ubl digital app.jpg".
Abdul
@Abdul C'est parce que ce chemin n'a pas de schéma Uri. Il devrait commencer par file://ou content://.
HB.
33

La solution MimeTypeMap ci-dessus a renvoyé null dans mon utilisation. Cela fonctionne et est plus simple:

Uri uri = Uri.fromFile(file);
ContentResolver cR = context.getContentResolver();
String mime = cR.getType(uri);
Jeb
la source
19
Cette méthode peut également renvoyer null.
Mister Smith
Il semble qu'il peut retourner null ou non, selon l'URI. Aucun organisme ne semble savoir pourquoi ;-(
Thomas Decaux
10
Si le média est sélectionné dans la galerie Android, TYPE est renvoyé. Si sélectionné dans le Gestionnaire de fichiers, null est renvoyé.
Rahul Rastogi
Je peux confirmer positivement ce que Rahul a dit, je viens de le tester et il a raison
Chris
Dans certains appareils, si je sélectionne une image de la galerie, elle renvoie également null
Ghanshyam Nayma
21

Version optimisée de la réponse de Jens avec null-safety et fallback-type.

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

Important : getFileExtensionFromUrl () ne fonctionne qu'avec des minuscules !


Mise à jour (19.03.2018)

Bonus: les méthodes ci-dessus sont une fonction d'extension Kotlin moins verbeuse :

fun File.getMimeType(fallback: String = "image/*"): String {
    return MimeTypeMap.getFileExtensionFromUrl(toString())
            ?.run { MimeTypeMap.getSingleton().getMimeTypeFromExtension(toLowerCase()) }
            ?: fallback // You might set it to */*
}
Tobias
la source
cela a fonctionné. un peu trop verbeux à mon goût cependant.
filthy_wizard
Bien sûr, cela peut être écrit de manière plus courte. Avec Kotlin probablement seulement deux ou trois lignes, cependant le renard était sur la sécurité et la toLoverCasepartie nulles .
Tobias
@filthy_wizard, a ajouté une version optimisée rien que pour vous ;-)
Tobias
Quant à moi, utiliser la méthode getPath () au lieu de toString () est plus clair, et il suffit d'utiliser la syntaxe d'accès à la propriété kotlin.
Leonid le
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();

    }
umerk44
la source
1
Fonctionne parfaitement pour moi! Mais que diriez-vous d'utiliser le FilenameUtils.getExetension (chemin) pour obtenir l'extension de fichier?
peterb
7

Faites super attention à umerk44 l » solution ci - dessus. getMimeTypeFromExtensioninvoque guessMimeTypeTypeFromExtensionet est SENSIBLE AU CAS. J'ai passé un après-midi là-dessus, puis j'ai examiné de plus près - getMimeTypeFromExtensionje reviendrai NULLsi vous le passez "JPG" alors qu'il retournera "image / jpeg" si vous le passez "jpg".

Mike Kogan
la source
5

Voici la solution que j'ai utilisée dans mon application 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;
    }
Mahendra Liya
la source
1
url? De nombreuses URL n'ont pas d'extension. Par exemple, cette page n'a pas d'extension. Pour l'url, vous devez utiliser une nouvelle URL (url) .openConnection (). GetRequestProperty ("Content-type");
barwnikk
5

Parfois, les réponses de Jeb et Jens ne fonctionnent pas et renvoient null. Dans ce cas, j'utilise la solution suivante. L'en-tête de fichier contient généralement une signature de type. Je l'ai lu et comparé avec connu dans la liste des signatures .

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

signatureIdest un index de signature dans un tableau de signatures. Par exemple,

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

Maintenant, j'ai le type de fichier même si l'URI du fichier ne l'a pas. Ensuite, j'obtiens le type de mime par type de fichier. Si vous ne savez pas quel type de mime obtenir, vous pouvez le trouver dans ce tableau .

Cela fonctionne pour de nombreux types de fichiers. Mais pour la vidéo, cela ne fonctionne pas, car vous avez besoin d'un codec vidéo connu pour obtenir un type mime. Pour obtenir le type mime de la vidéo, j'utilise MediaMetadataRetriever .

Sergei Vasilenko
la source
4

J'ai essayé d'utiliser des méthodes standard pour déterminer le type mime, mais je ne peux pas conserver l'extension de fichier en utilisant MimeTypeMap.getFileExtensionFromUrl(uri.getPath()). Cette méthode m'a renvoyé une chaîne vide. J'ai donc fait une solution non triviale pour conserver l'extension de fichier.

Voici la méthode renvoyant l'extension de fichier:

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

Et après avoir conservé l'extension de fichier, il est possible d'obtenir le type mime comme ci-dessous:

public String getMimeType(File file) {
    String mimeType = "";
    String extension = getExtension(file.getName());
    if (MimeTypeMap.getSingleton().hasExtension(extension)) {
        mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
    }
    return mimeType;
}
I. Shvedenenko
la source
Mec, cela a cloué toutes les réponses affichées ici sur ce problème! J'ai eu le même problème avec toutes les classes Legacy. Le problème était le même que celui que vous avez mentionné, a MimeTypeMap.getFileExtensionFromUrlrenvoyé une chaîne vide pour les noms de fichiers qui ont des caractères non valides selon l'implémentation interne d'un PatternMatcher. Cela a fonctionné complètement pour moi! J'ai adoré, aucun problème jusqu'à présent!
sud007
@JE. Shvedenenko String extension = file.getName().split("\\.")[1]aurait également fonctionné, éliminant ainsi la méthode getExtension ().
Shahood ul Hassan
Mais la chose est, que se passe-t-il si une mauvaise extension est utilisée lors de la création du fichier? L'extension devrait-elle être le seul juge du type mime?
Shahood ul Hassan
2

MimeTypeMappeut ne pas reconnaître certaines extensions de fichiers comme flv, mpeg, 3gpp, cpp. Vous devez donc réfléchir à la manière d'étendre le MimeTypeMap pour maintenir votre code. Voici un exemple.

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

De plus, voici une liste complète des types de mime

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

Min Thant Htoo
la source
2

Pour Xamarin Android (à partir de la réponse de @ HoaLe ci-dessus)

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;
}
La curiosité
la source
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
    }
Nilesh Panchal
la source
1

Alors que depuis un actif / fichier (notez que peu de cas sont absents du 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);
}

Pendant l'utilisation de ContentResolver

contentResolver.getType(uri)

Pendant la demande 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) {
    }
WCG
la source
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);
}
iamdhariot
la source
Veuillez fournir quelques explications. Cela aidera le premier lecteur à adapter son code et les autres lecteurs à tirer le meilleur parti de votre réponse.
Aurélien B
Merci pour votre réponse. Je le modifie avec une explication.
iamdhariot
1

J'ai fait face à un problème similaire. Jusqu'à présent, je sais que le résultat peut différer pour différents noms, alors est finalement arrivé à cette solution.

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;
}  
Ashish Sahu
la source
0

La solution ci-dessus a renvoyé null dans le cas d'un fichier .rar, en utilisant URLConnection.guessContentTypeFromName (url) a fonctionné dans ce cas.

Luis Barragan
la source
0

mime du fichier local:

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

vous avez plusieurs choix pour obtenir l'extension du fichier: comme: 1- String filename = uri.getLastPathSegment();voir ce lien

2-vous pouvez également utiliser ce code

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

mais ce n'est pas bon aproch. 3-si vous avez l'URI du fichier, utilisez ce code

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

4-si vous avez une URL, utilisez ce code:

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


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

return type;
}

profitez de votre code :)

John Smith
la source
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);}
YEH
la source
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);
}
Ali Bagheri
la source
0

A également renvoyé une valeur nulle dans mon chemin de cas était

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

comme travail autour de l'utilisation

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

donc la méthode ressemble à

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

en conséquence, il renvoie le résultat de la réussite:

audio / mpeg

J'espère que ça aide n'importe qui

Serg Burlaka
la source
0

Aucune des réponses ici n'est parfaite. Voici une réponse combinant les meilleurs éléments de toutes les réponses principales:

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;
        }
    }
}
Manish Kumar Sharma
la source
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());
                        }
Роман Зыков
la source
0

Je ne me rends pas compte pourquoi MimeTypeMap.getFileExtensionFromUrl()a des problèmes avec spaces et certains autres caractères, qui retourne "", mais j'ai juste écrit cette méthode pour changer le nom du fichier en un nom admis. C'est juste jouer avec l' Stringart. Cependant, cela fonctionne en quelque sorte. Grâce au procédé, le spaces existant dans le nom de fichier est transformé en un caractère souhaitable (qui, ici, est "x") via replaceAll(" ", "x")et d'autres caractères inappropriés sont transformés en un caractère approprié via URLEncoder. donc l'utilisation (selon les codes présentés dans la question et la réponse sélectionnée) devrait être quelque chose comme 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;
    }
elyar abad
la source