假设我有一个完整的文件路径:(/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;
}

但当我调用它时,它返回null。

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

当前回答

I don't realize why MimeTypeMap.getFileExtensionFromUrl() has problems with spaces and some other characters, that returns "", but I just wrote this method to change the file name to an admit-able one. It's just playing with Strings. However, It kind of works. Through the method, the spaces existing in the file name is turned into a desirable character (which, here, is "x") via replaceAll(" ", "x") and other unsuitable characters are turned into a suitable one via URLEncoder. so the usage (according to the codes presented in the question and the selected answer) should be something like 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;
    }

其他回答

请密切关注上面umerk44的解决方案。getMimeTypeFromExtension调用guessMimeTypeTypeFromExtension并且区分大小写。我花了一个下午的时间,然后仔细观察- getMimeTypeFromExtension将返回NULL,如果你传递它“JPG”,而它将返回“image/jpeg”,如果你传递它“JPG”。

在kotlin中,这要简单得多。

解决方案1:

fun getMimeType(file: File): String? = 
    MimeTypeMap.getSingleton().getMimeTypeFromExtension(file.extension)

方案二:(文件扩展名函数)

fun File.mimeType(): String? = 
    MimeTypeMap.getSingleton().getMimeTypeFromExtension(this.extension)

上面的解决方案在.rar文件的情况下返回null,使用URLConnection.guessContentTypeFromName(url)在这种情况下工作。

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

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

现在我有了文件类型,即使文件的URI没有。接下来我得到mime类型的文件类型。如果你不知道要获取哪种mime类型,你可以在这个表中找到proper。

它适用于许多文件类型。但是对于视频,它不起作用,因为你需要知道视频编解码器来获得mime类型。为了获得视频的mime类型,我使用mediametadatareretrieve。

以下是我在我的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;
    }