Android - 获取没有扩展名的文件的 MIME 类型

14
据我所知,只有三种方法可以从现有问题中获取MIME类型。
1)使用MimeTypeMap.getFileExtensionFromUrl通过文件扩展名来确定MIME类型。
2)使用URLConnection.guessContentTypeFromStream“猜测”inputStream的MIME类型。
3)使用ContentResolver通过内容Uri(content:\)获取MIME类型,context.getContentResolver().getType
然而,我只有文件对象,可获取的Uri是文件路径Uri(file:)。该文件没有扩展名。是否仍有办法获取该文件的MIME类型?或者有一种方法可以通过文件路径Uri确定内容Uri吗?

https://dev59.com/iGoy5IYBdhLWcg3wZdCr#30765320 - Oleksandr B
4个回答

20

你试过这个吗?对我有效(仅适用于图像文件)。

public static String getMimeTypeOfUri(Context context, Uri uri) {
    BitmapFactory.Options opt = new BitmapFactory.Options();
    /* The doc says that if inJustDecodeBounds set to true, the decoder
     * will return null (no bitmap), but the out... fields will still be
     * set, allowing the caller to query the bitmap without having to
     * allocate the memory for its pixels. */
    opt.inJustDecodeBounds = true;

    InputStream istream = context.getContentResolver().openInputStream(uri);
    BitmapFactory.decodeStream(istream, null, opt);
    istream.close();

    return opt.outMimeType;
}

当然,您也可以使用其他方法,例如像这样使用BitmapFactory.decodeFileBitmapFactory.decodeResource

public static String getMimeTypeOfFile(String pathName) {
    BitmapFactory.Options opt = new BitmapFactory.Options();
    opt.inJustDecodeBounds = true;
    BitmapFactory.decodeFile(pathName, opt);
    return opt.outMimeType;
}

如果无法确定 MIME 类型,它将返回 null。


1
BitmapFactory 只会确定图像文件的 MIME 类型。 - Jason Hu

9
还有获取文件的MIME类型的方法吗? 仅凭文件名无法确定。
或者有一种方法可以从文件路径Uri确定内容Uri吗? 不一定存在“内容Uri”。您可以尝试在MediaStore中查找文件,并查看是否因某种原因它已经知道了MIME类型。MediaStore可能知道MIME类型,也可能不知道,如果它不知道,则无法确定。如果您确实拥有content:// Uri,则使用ContentResolver上的getType()方法获取MIME类型。

3

首字节包含文件扩展名

@Nullable
public static String getFileExtFromBytes(File f) {
    FileInputStream fis = null;
    try {
        fis = new FileInputStream(f);
        byte[] buf = new byte[5]; //max ext size + 1
        fis.read(buf, 0, buf.length);
        StringBuilder builder = new StringBuilder(buf.length);
        for (int i=1;i<buf.length && buf[i] != '\r' && buf[i] != '\n';i++) {
            builder.append((char)buf[i]);
        }
        return builder.toString().toLowerCase();
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        try {
            if (fis != null) {
                fis.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    return null;
}

1
要获取没有扩展名的文件的MIME类型,您需要使用不同的方法。其中一种方法是读取文件的前几个字节,并根据文件格式签名(也称为“魔数”)确定MIME类型。
import java.io.FileInputStream
import java.nio.ByteBuffer
import java.nio.ByteOrder

fun getMimeTypeWithoutExtension(filePath: String): String {
val magicNumbers = mapOf(
    0x89.toByte() to "image/png",
    0xff.toByte() to "image/jpeg",
    0x47.toByte() to "image/gif",
    0x49.toByte() to "image/tiff",
    0x4d.toByte() to "image/tiff",
    0x25.toByte() to "application/pdf",
    0x50.toByte() to "application/vnd.ms-powerpoint",
    0xD0.toByte() to "application/vnd.ms-word",
    0x43.toByte() to "application/vnd.ms-word",
    0x53.toByte() to "application/vnd.ms-word"
)

var mimeType = "application/octet-stream"
FileInputStream(filePath).use { inputStream ->
    val buffer = ByteArray(1024)
    inputStream.read(buffer, 0, buffer.size)
    val magicNumber = ByteBuffer.wrap(buffer).order(ByteOrder.BIG_ENDIAN).get().toInt() and 0xff
    mimeType = magicNumbers[magicNumber.toByte()] ?: mimeType
}
return mimeType
}

此代码使用FileInputStream类将文件的第一个字节读入ByteArray中。然后将该字节提取为整数,并用于在魔术数字和MIME类型映射表中查找相应的MIME类型。如果无法确定MIME类型,则函数将返回“application/octet-stream”作为默认值。

请注意,此代码仅检查文件的第一个字节,因此可能无法准确确定没有扩展名的文件的MIME类型。为了获得更准确的结果,您可能需要检查文件的其他字节或使用提供更全面的MIME类型检测的库。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接