Jason Hu
Jason Hu

Reputation: 1267

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.

1) Determining it from the file extension using MimeTypeMap.getFileExtensionFromUrl

2) "Guess" using the inputStream with URLConnection.guessContentTypeFromStream

3) Using the ContentResolver to get the MIME type using content Uri (content:\) context.getContentResolver().getType

However, I only have the file object, with the obtainable Uri being the file path Uri (file:). The file does not have an extension. Is there still a way to get the MIME type of the file? Or a way to determine the content Uri from the file path Uri?

Upvotes: 15

Views: 15963

Answers (4)

vaidik limbachiya
vaidik limbachiya

Reputation: 111

In order to get the MIME type of a file that doesn't have an extension, you'll need to use a different approach. 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").

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. 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. If the MIME type cannot be determined, the function returns "application/octet-stream" as a default.

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. 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.

Upvotes: 2

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

Upvotes: 3

CommonsWare
CommonsWare

Reputation: 1007544

Is there still a way to get the MIME type of the file?

Not from the filename alone.

Or a way to determine the content Uri from the file path Uri?

There is not necessarily any "content 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 may or may not know the MIME type, and if it does not, there is no way to determine it.

If you do have content:// Uri, use getType() on a ContentResolver to get the MIME type.

Upvotes: 9

fikr4n
fikr4n

Reputation: 3430

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:

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.

Upvotes: 21

Related Questions