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

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

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

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

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

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();

    }

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".


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

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 .


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

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

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

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

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) {
    }

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

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

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.


0

mime du fichier local:

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

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


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

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


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

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

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;
    }
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.