Come determinare il tipo di file MIME in Android?


176

Supponiamo che io abbia un percorso completo di file come: (/ sdcard / tlogo.png). Voglio sapere il suo tipo mime.

Ho creato una funzione per questo

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

ma quando lo chiamo, restituisce null.

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

Risposte:


323

Prima di tutto, dovresti considerare di chiamare MimeTypeMap#getMimeTypeFromExtension(), in questo modo:

// 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
grazie lavoro per me e un'altra soluzione del mio problema è: stringa statica pubblica getMimeType (percorso stringa, contesto di contesto) {String extention = path.substring (path.lastIndexOf (".")); String mimeTypeMap = MimeTypeMap.getFileExtensionFromUrl (estensione); String mimeType = MimeTypeMap.getSingleton () .getMimeTypeFromExtension (mimeTypeMap); return mimeType;}
Sushant Bhatnagar il

13
E se il file non ha la buona estensione? una persona può creare un .mp3 e contiene del testo
throrin19

2
Quindi dovresti effettivamente aprire il file e controllare il numero magico (a seconda del formato ofc) nel lead-in - questo, tuttavia, presuppone anche che la persona che rinomina i file txt in mp3 non abbia semplicemente scritto ID3nel inizio del suo testo per rovinare ancora di più te.
Jens,

1
Se il file ha un'estensione sconosciuta. Il metodo ritorna */*?

3
Se hai il percorso del file come / storage / emulato / 0 / Download / images (4) .jpg e chiedi il mimetype, restituisce null.
Kalaiselvan,

165

Rileva il tipo mime di qualsiasi file

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
Questa dovrebbe essere la risposta corretta. toLowerCase()ha fatto il trucco.
Rajat Saxena,

1
Questa è di gran lunga la risposta migliore ma fallisce miseramente se il nome del file ha un carattere speciale, nel mio caso un apostrophe! Per esempio. nome file = Don't go baby.mp3. L' PatternMatcherinterno MimeTypeMap.getFileExtensionFromUrl()non può gestire il nome del file e restituisce String vuoto; null risulta essere la stringa mimetype!
sud007

Esiste una soluzione simile ma priva di errori di I. ShvedenenkoWorked per i problemi che ho indicato sopra. Ma questa risposta era un puntatore nella direzione corretta.
sud007

questo codice restituisce null con String "/ storage / emulato / 0 / dcim / screenshots / screenshot_20190319-123828_ubl digital app.jpg".
Abdul

@Abdul È perché quel percorso non ha uno schema Uri. Dovrebbe iniziare con file://o content://.
HB.

33

La soluzione MimeTypeMap di cui sopra ha restituito null nel mio utilizzo. Funziona ed è più semplice:

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

19
Questo metodo può anche restituire null.
Mister Smith,

Sembra che possa restituire null o no, secondo l'URI. Nessun corpo sembra sapere perché ;-(
Thomas Decaux,

10
Se il supporto viene selezionato dalla galleria Android, viene restituito TYPE. Se selezionato da File Manager, viene restituito null.
Rahul Rastogi,

Posso confermare positivamente quello che ha detto Rahul, l'ho appena testato e ha ragione
Chris,

In alcuni dispositivi, se seleziono l'immagine dalla galleria, anch'essa restituisce null
Ghanshyam Nayma,

21

Versione ottimizzata della risposta di Jens con null-safety e 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;
}

Importante : getFileExtensionFromUrl () funziona solo con lettere minuscole !


Aggiornamento (19.03.2018)

Bonus: sopra i metodi come una funzione di estensione di Kotlin meno dettagliata :

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

questo ha funzionato. un po 'troppo prolisso per i miei gusti.
filthy_wizard

Ovviamente questo può essere uno scrittore in un modo più breve. Con Kotlin probabilmente solo due o tre righe, tuttavia il foxus era in totale sicurezza e toLoverCaseparte.
Tobias,

@filthy_wizard, aggiunta una versione ottimizzata solo per te ;-)
Tobias

Per quanto mi riguarda, usare il metodo getPath () invece di toString () è più chiaro, e solo il percorso che usa la sintassi di accesso alle proprietà di 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
Funziona perfettamente per me! Ma che ne dici di usare FilenameUtils.getExetension (percorso) per ottenere l'estensione del file?
peterb,

7

Prestare molta attenzione a super- umerk44 's soluzione sopra. getMimeTypeFromExtensioninvoca guessMimeTypeTypeFromExtensioned è CASE SENSITIVE. Ho trascorso un pomeriggio su questo, poi ho dato un'occhiata più da vicino - getMimeTypeFromExtensiontornerà NULLse lo passi "JPG" mentre restituirà "image / jpeg" se lo passi "jpg".


5

Ecco la soluzione che ho usato nella mia app per 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? Un sacco di url non ha estensione. Ad esempio questa pagina non ha estensione. Per url dovresti usare il nuovo URL (url) .openConnection (). GetRequestProperty ("Content-type");
Barwnikk,

5

A volte le risposte di Jeb e Jens non funzionano e restituiscono null. In questo caso utilizzo la soluzione follow. L'intestazione del file di solito contiene la firma del tipo. L'ho letto e confrontato con noto nell'elenco delle firme .

/**
 *
 * @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è un indice di firma nella matrice di firme. Per esempio,

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

Ora ho il tipo di file anche se non l'URI del file. Successivamente ottengo il tipo mime per tipo di file. Se non sai quale tipo di mime ottenere, puoi trovare quello giusto in questa tabella .

Funziona con molti tipi di file. Ma per i video non funziona, perché è necessario conoscere un codec video per ottenere un tipo MIME. Per ottenere il tipo mime del video, utilizzo MediaMetadataRetriever .


4

Ho provato a utilizzare i metodi standard per determinare il tipo mime, ma non riesco a conservare l'estensione del file utilizzando MimeTypeMap.getFileExtensionFromUrl(uri.getPath()) . Questo metodo mi ha restituito una stringa vuota. Quindi ho creato una soluzione non banale per mantenere l'estensione del file.

Ecco il metodo che restituisce l'estensione del file:

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

E avendo mantenuto l'estensione del file, è possibile ottenere il tipo mime come di seguito:

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

Amico, questo ha inchiodato tutte le risposte postate qui su questo problema! Ho avuto lo stesso problema con tutte le classi Legacy. Il problema era lo stesso che hai menzionato, ha MimeTypeMap.getFileExtensionFromUrlrestituito una stringa vuota per i nomi di file che hanno caratteri non validi secondo l'implementazione interna di a PatternMatcher. Questo ha funzionato completamente per me! Mi è piaciuto molto, nessun problema finora!
sud007,

@IO. Anche Shvedenenko String extension = file.getName().split("\\.")[1]avrebbe funzionato, eliminando così il metodo getExtension ().
Shahood ul Hassan,

Ma il fatto è che cosa succede se durante la creazione del file viene utilizzata un'estensione errata? L'estensione dovrebbe essere l'unico giudice del tipo mime?
Shahood ul Hassan,


2

Per Xamarin Android (dalla risposta di @ HoaLe sopra)

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

Mentre da asset / file (si noti che mancano pochi casi da 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);
}

Durante l'utilizzo di ContentResolver

contentResolver.getType(uri)

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

Si prega di fornire alcune spiegazioni. Aiuterà il lettore iniziale ad adattare il suo codice e altri lettori per ottenere il massimo valore dalla tua risposta.
Aurélien B,

Grazie per la risposta. Lo modifico con una spiegazione.
iamdhariot,

1

Ho affrontato un problema simile. Finora so che il risultato potrebbe essere diverso per nomi diversi, quindi alla fine è arrivata questa soluzione.

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 soluzione di cui sopra ha restituito null in caso di file .rar, utilizzando URLConnection.guessContentTypeFromName (url) ha funzionato in questo caso.


0

mime dal file locale:

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

0

hai una scelta multipla per ottenere l'estensione del file: come: 1- String filename = uri.getLastPathSegment();vedi questo link

2-puoi usare anche questo codice

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

ma questo non è un buon aproch. 3-se si dispone di URI del file, utilizzare questo codice

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

4-se si dispone di URL, utilizzare questo codice:

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


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

return type;
}

goditi il ​​tuo codice :)


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

Ha anche restituito un valore null nel mio caso

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

come aggirare l'uso

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

quindi il metodo sembra

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

di conseguenza restituisce il risultato di successo:

audio / mpeg

Spero che aiuti qualcuno


0

Nessuna delle risposte qui è perfetta. Ecco una risposta che combina i migliori elementi di tutte le risposte migliori:

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

Non capisco perché MimeTypeMap.getFileExtensionFromUrl()abbia problemi con se con spacealcuni altri caratteri, che ritorni "", ma ho appena scritto questo metodo per cambiare il nome del file in uno ammissibile. Sta solo giocando con Strings. Tuttavia, funziona in qualche modo. Attraverso il metodo, le spaces esistenti nel nome del file vengono trasformate in un carattere desiderabile (che, qui, è "x") via replaceAll(" ", "x")e altri caratteri non idonei vengono trasformati in un carattere adatto tramite URLEncoder. quindi l'uso (secondo i codici presentati nella domanda e la risposta selezionata) dovrebbe essere qualcosa di simile 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;
    }
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.