Como determinar o tipo de arquivo MIME no android?


176

Suponha que eu tenha um caminho completo do arquivo como: (/ sdcard / tlogo.png). Eu quero saber o seu tipo de mímica.

Eu criei uma função para isso

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

mas quando eu chamo, ele retorna nulo.

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

Respostas:


323

Em primeiro lugar, considere ligar MimeTypeMap#getMimeTypeFromExtension()assim:

// 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
obrigado trabalho para mim e outra solução do meu problema é: public estático String getMimeType (caminho da String, contexto de contexto) {Extensão da string = path.substring (path.lastIndexOf (".")); String mimeTypeMap = MimeTypeMap.getFileExtensionFromUrl (extensão); String mimeType = MimeTypeMap.getSingleton () .getMimeTypeFromExtension (mimeTypeMap); return mimeType;}
Sushant Bhatnagar

13
E se o arquivo não tiver a boa extensão? uma pessoa pode fazer um .mp3 e ele contém texto
throrin19

2
Então, você realmente precisa abrir o arquivo e verificar o número mágico (dependendo do formato ofc) no lead-in - isso, no entanto, também pressupõe que a pessoa que renomeou os arquivos txt para mp3 não apenas escreveu ID3no início do seu texto para mexer com você ainda mais.
Jens

1
Se o arquivo tiver uma extensão desconhecida. O método retorna */*?

3
Se você tiver um caminho de arquivo como / storage / emulated / 0 / Download / images (4) .jpg e solicitar o tipo mimetype, ele retornará nulo.
Kalaiselvan

165

Detectar tipo MIME de qualquer arquivo

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
Essa deve ser a resposta correta. toLowerCase()fez o truque.
Rajat Saxena

1
Esta é de longe a melhor resposta, mas falha miseravelmente se o nome do arquivo tiver um caractere especial, no meu caso um apostrophe! Por exemplo. nome do arquivo = Don't go baby.mp3. O PatternMatcherinterior MimeTypeMap.getFileExtensionFromUrl()não pode manipular o nome do arquivo e retorna String vazia; null passa a ser o tipo de tipo String!
sud007

Existe uma solução semelhante, mas sem erros, abaixo, da I. ShvedenenkoWorked, para os problemas que eu apontei acima. Mas essa resposta foi um indicador na direção correta.
sud007

esse código retorna nulo com a string "/ storage / emulated / 0 / dcim / screenshots / screenshot_20190319-123828_ubl digital app.jpg".
Abdul

@ Abdul É porque esse caminho não possui um esquema de Uri. Deve começar com file://ou content://.
HB.

33

A solução MimeTypeMap acima retornou nula no meu uso. Isso funciona e é mais fácil:

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

19
Este método também pode retornar nulo.
Mister Smith

Parece que pode retornar nulo ou não, de acordo com o URI. Nenhum corpo parece saber por que ;-(
Thomas Decaux

10
Se a mídia for selecionada na galeria do Android, TYPE será retornado. Se selecionado no Gerenciador de Arquivos, nulo será retornado.
Rahul Rastogi

Eu posso positivamente confirmar o que Rahul disse, só testei e ele está certo
Chris

Em alguns dispositivos, se eu selecionar uma imagem da galeria também está retornando null
Ghanshyam Nayma

21

Versão otimizada do respondere de Jens com segurança nula e tipo de fallback.

@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 () funciona apenas com letras minúsculas !


Atualização (19.03.2018)

Bônus: métodos acima como uma função de extensão Kotlin menos detalhada :

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

isso funcionou. um pouco excessivamente detalhado para o meu gosto.
filthy_wizard

É claro que isso pode ser feito de maneira mais curta. Com Kotlin provavelmente apenas duas ou três linhas, no entanto, o foxus estava na segurança e toLoverCaseparte nulas .
Tobias

@filthy_wizard, acrescentou uma versão otimizada para você ;-)
Tobias

Quanto a mim, usar o método getPath () em vez de toString () é mais claro e apenas o caminho usando a sintaxe de acesso à propriedade 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
Funciona perfeito para mim! Mas que tal usar o FilenameUtils.getExetension (path) para obter a extensão do arquivo?
Peterb

7

Preste super perto atenção para umerk44 's solução acima. getMimeTypeFromExtensioninvoca guessMimeTypeTypeFromExtensione é sensível a maiúsculas e minúsculas. Passei uma tarde nisso e, em seguida, olhei mais de perto - getMimeTypeFromExtensionretornará NULLse você passá-lo "JPG", enquanto retornará "imagem / jpeg" se passá-lo "jpg".


5

Aqui está a solução que eu usei no meu aplicativo 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? Muitos URLs não têm extensão. Por exemplo, esta página não tem extensão. Para url, você deve usar o novo URL (url) .openConnection (). GetRequestProperty ("Content-type");
barwnikk

5

Às vezes, as respostas de Jeb e Jens não funcionam e retornam nulas. Neste caso, eu uso follow solution. O chefe do arquivo geralmente contém assinatura de tipo. Eu li e comparo com o conhecido na lista de assinaturas .

/**
 *
 * @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é um índice de assinatura na matriz de assinaturas. Por exemplo,

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

Agora eu tenho o tipo de arquivo, mesmo que o URI do arquivo não tenha. Em seguida, recebo o tipo mime por tipo de arquivo. Se você não souber qual tipo de mímica obter, poderá encontrar o apropriado nesta tabela .

Funciona para muitos tipos de arquivos. Mas para o vídeo não funciona, porque você precisa de um codec de vídeo conhecido para obter um tipo de mímica. Para obter o tipo MIME do vídeo, uso o MediaMetadataRetriever .


4

Tentei usar métodos padrão para determinar o tipo de mímica, mas não consigo reter a extensão do arquivo usando MimeTypeMap.getFileExtensionFromUrl(uri.getPath()). Este método me devolveu uma string vazia. Então, eu fiz uma solução não trivial para manter a extensão do arquivo.

Aqui está o método retornando a extensão do arquivo:

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, mantendo a extensão do arquivo, é possível obter o tipo mime como abaixo:

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

Cara, isso acertou todas as respostas postadas aqui sobre esse problema! Eu tive o mesmo problema com todas as classes do Legacy. O problema foi o mesmo que você mencionou, MimeTypeMap.getFileExtensionFromUrlretornou uma string vazia para os nomes de arquivos que possuem caracteres inválidos conforme a implementação interna de a PatternMatcher. Isso funcionou para mim completamente! Adorei, sem problemas até agora!
sud007

@EU. Shvedenenko String extension = file.getName().split("\\.")[1]também teria funcionado, eliminando o método getExtension ().
Shahood ul Hassan

Mas o problema é: e se uma extensão errada for usada durante a criação do arquivo? A extensão deve ser o único juiz do tipo MIME?
Shahood ul Hassan


2

Para Xamarin Android (da resposta da @ HoaLe acima)

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

Enquanto estiver no ativo / arquivo (observe que faltam alguns casos no 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);
}

Enquanto usa o ContentResolver

contentResolver.getType(uri)

Enquanto a solicitação 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);
}

Por favor, forneça alguma explicação. Isso ajudará o leitor inicial a adaptar seu código e outros leitores a obter o máximo valor da sua resposta.
Aurélien B

obrigado pela sua resposta. Eu edito com explicação.
precisa saber é o seguinte

1

Eu enfrentei um problema semelhante. Até agora eu sei que o resultado pode ser diferente para nomes diferentes, então finalmente cheguei a esta solução.

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

A solução acima retornou nulo no caso do arquivo .rar, usando URLConnection.guessContentTypeFromName (url) trabalhado nesse caso.


0

mime do arquivo local:

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

0

você tem várias opções para obter a extensão do arquivo: como: 1- String filename = uri.getLastPathSegment();veja este link

2-você pode usar esse código também

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

mas isso não é bom dia. 3 - se você tiver um URI de arquivo, use este código

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

4-se você tiver URL, use este código:

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


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

return type;
}

aproveite seu código :)


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

Também retornou valor nulo no meu caminho de caso foi

/ armazenamento / emulado / 0 / Música / 01 - Ghost on the Dance Floor.mp3

como contornar o uso

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

então método parece

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

como resultado, ele retorna resultado de sucesso:

audio / mpeg

Espero que ajude alguém


0

Nenhuma das respostas aqui é perfeita. Aqui está uma resposta que combina os melhores elementos de todas as principais respostas:

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

Não sei por que MimeTypeMap.getFileExtensionFromUrl()tem problemas com spaces e com outros caracteres, isso retorna "", mas acabei de escrever esse método para alterar o nome do arquivo para um nome admissível. Está apenas brincando com Strings. No entanto, isso meio que funciona. Através do método, os spaces existentes no nome do arquivo são transformados em um caractere desejável (que, aqui, é "x") via replaceAll(" ", "x")e outros caracteres inadequados são transformados em um caractere adequado URLEncoder. portanto, o uso (de acordo com os códigos apresentados na pergunta e na resposta selecionada) deve ser algo parecido 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;
    }
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.