Reputation: 1267
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
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
Reputation: 31
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
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
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