简体   繁体   English

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

[英]Android - Get MIME type from file without extension

As far as I'm aware there's only three ways to get the MIME type from reading the existing questions.据我所知,只有三种方法可以通过阅读现有问题来获取 MIME 类型。

1) Determining it from the file extension using MimeTypeMap.getFileExtensionFromUrl 1)使用MimeTypeMap.getFileExtensionFromUrl从文件扩展名确定它

2) "Guess" using the inputStream with URLConnection.guessContentTypeFromStream 2)“猜测”使用带有URLConnection.guessContentTypeFromStreaminputStream

3) Using the ContentResolver to get the MIME type using content Uri (content:\) context.getContentResolver().getType 3) 使用ContentResolver使用内容 Uri (content:\) context.getContentResolver().getType获取 MIME 类型

However, I only have the file object, with the obtainable Uri being the file path Uri (file:).但是,我只有文件object,可获取的Uri是文件路径Uri (file:)。 The file does not have an extension.该文件没有扩展名。 Is there still a way to get the MIME type of the file?还有办法获取文件的 MIME 类型吗? Or a way to determine the content Uri from the file path Uri?或者从文件路径 Uri 中确定内容 Uri 的方法?

Have you tried this? 你试过这个吗? It works for me ( only for image files ). 它适用于我( 仅适用于图像文件 )。

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

Of course you can also use other methods, such as BitmapFactory.decodeFile or BitmapFactory.decodeResource like this: 当然你也可以使用其他方法,比如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;
}

It will return null if failed to determine the MIME type. 如果无法确定MIME类型,它将返回null。

Is there still a way to get the MIME type of the file? 还有办法获取文件的MIME类型吗?

Not from the filename alone. 不仅仅来自文件名。

Or a way to determine the content Uri from the file path Uri? 或者从文件路径Uri确定内容Uri的方法?

There is not necessarily any "content Uri". 没有任何“内容Uri”。 You are welcome to try to find the file in MediaStore and see if, for some reason, it happens to know the MIME type. 欢迎您尝试在MediaStore查找该文件,并查看是否出于某种原因知道MIME类型。 MediaStore may or may not know the MIME type, and if it does not, there is no way to determine it. MediaStore可能知道也可能不知道MIME类型,如果不知道,则无法确定它。

If you do have content:// Uri , use getType() on a ContentResolver to get the MIME type. 如果content:// Uri ,使用getType()ContentResolver获得MIME类型。

First bytes contains file extension 第一个字节包含文件扩展名

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

In order to get the MIME type of a file that doesn't have an extension, you'll need to use a different approach.为了获得没有扩展名的文件的 MIME 类型,您需要使用不同的方法。 One way to do this is to read the first few bytes of the file and determine the MIME type based on the file format signature (also known as "magic numbers").一种方法是读取文件的前几个字节并根据文件格式签名(也称为“幻数”)确定 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
}

This code uses the FileInputStream class to read the first byte of the file into a ByteArray.此代码使用 FileInputStream class 将文件的第一个字节读入 ByteArray。 The byte is then extracted as an integer and used to look up the corresponding MIME type in a map of magic numbers and MIME types.然后将该字节提取为 integer,并用于在 map 的幻数和 MIME 类型中查找相应的 MIME 类型。 If the MIME type cannot be determined, the function returns "application/octet-stream" as a default.如果无法确定 MIME 类型,则 function 默认返回“application/octet-stream”。

Note that this code is only checking the first byte of the file, so it may not always accurately determine the MIME type of a file without an extension.请注意,此代码仅检查文件的第一个字节,因此它可能无法始终准确地确定没有扩展名的文件的 MIME 类型。 For more accurate results, you may need to check additional bytes of the file or use a library that provides more comprehensive MIME type detection.为获得更准确的结果,您可能需要检查文件的其他字节或使用提供更全面的 MIME 类型检测的库。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM