如何确定android中的MIME类型?

Sus*_*gar 162 filesystems android mime-types

假设我有一个完整的文件路径,如:(/ sdcard/tlogo.png).我想知道它的mime类型.

我为它创建了一个函数

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;
}
Run Code Online (Sandbox Code Playgroud)

但是当我调用它时,它返回null.

File file = new File(filePath);
String fileType=CommonFunctions.getMimeType(file, context);
Run Code Online (Sandbox Code Playgroud)

Jen*_*ens 302

首先,您应该考虑调用MimeTypeMap#getMimeTypeFromExtension(),如下所示:

// 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;
}
Run Code Online (Sandbox Code Playgroud)

  • 如果文件没有良好的扩展名?一个人可以制作一个.mp3,它包含文字 (12认同)
  • 感谢为我工作,我的问题的另一个解决方案是:public static String getMimeType(String path,Context context){String extention = path.substring(path.lastIndexOf(".")); String mimeTypeMap = MimeTypeMap.getFileExtensionFromUrl(extention); String mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(mimeTypeMap); return mimeType;} (3认同)
  • 这是不可靠的。依赖文件扩展名并从中确定文件类型是很糟糕的。我不敢相信@throrin19 提到的如此重要的事情被忽略了。 (3认同)
  • 如果您的文件路径为/ storage/emulated/0/Download/images(4).jpg并且您要求使用mimetype,则返回null. (3认同)
  • 然后你需要实际打开文件并检查导入中的幻数(取决于c的格式) - 但是,这也假设将txt文件重命名为mp3的人不只是写`ID3 `在他的文字的开头,更惹你. (2认同)

小智 147

检测任何文件的mime类型

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;
}
Run Code Online (Sandbox Code Playgroud)

  • 这应该是正确的答案.`toLowerCase()`做了这个伎俩. (5认同)
  • 这是迄今为止最好的答案,但如果文件名具有特殊字符,则它会失败,在我的情况下是“撇号”!例如。文件名 = `别走 baby.mp3`。`MimeTypeMap.getFileExtensionFromUrl()`中的`PatternMatcher`无法处理文件名并返回空字符串;null 出来是 mimetype 字符串! (3认同)

Jeb*_*Jeb 32

上面的MimeTypeMap解决方案在我的使用中返回null.这很有效,而且更容易:

Uri uri = Uri.fromFile(file);
ContentResolver cR = context.getContentResolver();
String mime = cR.getType(uri);
Run Code Online (Sandbox Code Playgroud)

  • 此方法也可以返回null. (18认同)
  • 如果从Android库中选择媒体,则返回TYPE.如果从文件管理器中选择,则返回null. (10认同)
  • 此方法仅适用于Content Uri。 (3认同)

Tob*_*ias 17

优化的版本的answere与空安全和回退类型.

@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;
}
Run Code Online (Sandbox Code Playgroud)

重要说明:getFileExtensionFromUrl()仅适用于小写!


更新(19.03.2018)

额外奖励:以上方法作为较少详细的Kotlin扩展功能:

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


ume*_*k44 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();

    }
Run Code Online (Sandbox Code Playgroud)


tan*_*993 9

在 kotlin 中,这要简单得多。

解决方案一:

fun getMimeType(file: File): String? = 
    MimeTypeMap.getSingleton().getMimeTypeFromExtension(file.extension)
Run Code Online (Sandbox Code Playgroud)

方案二:(文件扩展功能)

fun File.mimeType(): String? = 
    MimeTypeMap.getSingleton().getMimeTypeFromExtension(this.extension)
Run Code Online (Sandbox Code Playgroud)


小智 7

付超密切关注umerk44解决方案上面.getMimeTypeFromExtension调用guessMimeTypeTypeFromExtension并且是CASE SENSITIVE.我花了一个下午然后仔细看看 - 如果你把它传给它"JPG" getMimeTypeFromExtension将返回,NULL如果你传递"jpg",它将返回"image/jpeg".


Dat*_*Lag 6

编辑

我为此创建了一个小型图书馆。但底层代码几乎是一样的。

它可以在 GitHub 上找到

MimeMagic-Android

解决方案 2020 年 9 月

使用科特林

fun File.getMimeType(context: Context): String? {
    if (this.isDirectory) {
        return null
    }

    fun fallbackMimeType(uri: Uri): String? {
        return if (uri.scheme == ContentResolver.SCHEME_CONTENT) {
            context.contentResolver.getType(uri)
        } else {
            val extension = MimeTypeMap.getFileExtensionFromUrl(uri.toString())
            MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension.toLowerCase(Locale.getDefault()))
        }
    }

    fun catchUrlMimeType(): String? {
        val uri = Uri.fromFile(this)

        return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            val path = Paths.get(uri.toString())
            try {
                Files.probeContentType(path) ?: fallbackMimeType(uri)
            } catch (ignored: IOException) {
                fallbackMimeType(uri)
            }
        } else {
            fallbackMimeType(uri)
        }
    }

    val stream = this.inputStream()
    return try {
        URLConnection.guessContentTypeFromStream(stream) ?: catchUrlMimeType()
    } catch (ignored: IOException) {
        catchUrlMimeType()
    } finally {
        stream.close()
    }
}
Run Code Online (Sandbox Code Playgroud)

这似乎是最好的选择,因为它结合了以前的答案。

首先,它尝试使用 URLConnection.guessContentTypeFromStream 获取类型,但如果失败或返回 null,它会尝试使用 Android O 及更高版本获取 mimetype

java.nio.file.Files
java.nio.file.Paths
Run Code Online (Sandbox Code Playgroud)

否则,如果 Android 版本低于 O 或方法失败,它将使用 ContentResolver 和 MimeTypeMap 返回类型


Mah*_*iya 5

这是我在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;
    }
Run Code Online (Sandbox Code Playgroud)

  • 网址?很多网址没有扩展名。例如,此页面没有扩展名。对于 url,您应该使用 new URL(url).openConnection().getRequestProperty("Content-type"); (2认同)

Ser*_*nko 5

有时Jeb和Jens的答案不起作用,并且返回null。在这种情况下,我使用关注解决方案。文件头通常包含类型签名。我阅读并与签名列表中的已知签名进行比较。

/**
 *
 * @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;
}
Run Code Online (Sandbox Code Playgroud)

signatureId是签名数组中签名的索引。例如,

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;
}
Run Code Online (Sandbox Code Playgroud)

现在我有了文件类型,即使文件的URI还没有。接下来,按文件类型获取mime类型。如果您不知道要获取哪种MIME类型,则可以在此表中找到适当的类型。

它适用于许多文件类型。但是对于视频来说,它是行不通的,因为您需要使用已知的视频编解码器才能获得哑剧类型。要获取视频的mime类型,请使用MediaMetadataRetriever


小智 5

我尝试使用标准方法来确定 MIME 类型,但我无法使用MimeTypeMap.getFileExtensionFromUrl(uri.getPath()). 此方法返回一个空字符串。所以我做了一个重要的解决方案来保留文件扩展名。

这是返回文件扩展名的方法:

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 "";
}
Run Code Online (Sandbox Code Playgroud)

并且保留了文件扩展名,可以得到如下的 MIME 类型:

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