如何确定在Android的文件的MIMEtypes?

假设我有一个完整的文件path,如:(/ sdcard / tlogo.png)。 我想知道它的MIMEtypes。

我为它创build了一个函数

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

首先,你应该考虑调用MimeTypeMap#getMimeTypeFromExtension() ,像这样:

 // url = file path or whatever suitable URL you want. public static String getMimeType(String url) { String type = null; String extension = MimeTypeMap.getFileExtensionFromUrl(url); if (extension != null) { type = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension); } return type; } 

检测我的MIMEtypes

 public String getMimeType(Uri uri) { String mimeType = null; if (uri.getScheme().equals(ContentResolver.SCHEME_CONTENT)) { ContentResolver cr = getAppContext().getContentResolver(); mimeType = cr.getType(uri); } else { String fileExtension = MimeTypeMap.getFileExtensionFromUrl(uri .toString()); mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension( fileExtension.toLowerCase()); } return mimeType; } 

上面的MimeTypeMap解决scheme在我的用法中返回null。 这工作,更容易:

 Uri uri = Uri.fromFile(file); ContentResolver cR = context.getContentResolver(); String mime = cR.getType(uri); 
 File file = new File(path, name); MimeTypeMap mime = MimeTypeMap.getSingleton(); int index = file.getName().lastIndexOf('.')+1; String ext = file.getName().substring(index).toLowerCase(); String type = mime.getMimeTypeFromExtension(ext); intent.setDataAndType(Uri.fromFile(file), type); try { context.startActivity(intent); } catch(ActivityNotFoundException ex) { ex.printStackTrace(); } 

Jens回复的优化版本。

 @NonNull static String getMimeType(@NonNull File file) { String type = null; final String url = file.toString(); final String extension = MimeTypeMap.getFileExtensionFromUrl(url); if (extension != null) { type = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension.toLowerCase()); } if (type == null) { type = "image/*"; // fallback type. You might set it to */* } return type; } 

重要提示 :getFileExtensionFromUrl()只能使用小写

以上关注umerk44解决scheme。 getMimeTypeFromExtension调用guessMimeTypeTypeFromExtension并且是CASE SENSITIVE。 我花了一个下午,然后仔细看看 – getMimeTypeFromExtension将返回NULL,如果您通过它“JPG”,而它会返回“图像/ jpeg”,如果你通过它“jpg”

有时Jeb和Jens的答案不起作用,并返回null。 在这种情况下我使用以下解决scheme。 文件头通常包含types签名。 我读它,并与签名列表中的已知比较。

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

现在我有文件types,即使文件的URI没有。 接下来,我通过文件types获得mimetypes。 如果你不知道要获得哪种MIMEtypes,你可以在这个表格中find合适的。

它适用于很多文件types。 但是对于video来说这是行不通的,因为你需要知道video编解码器来获得一个MIMEtypes。 要获得video的MIMEtypes,我使用MediaMetadataRetriever 。

以下是我在Android应用程序中使用的解决scheme:

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

MimeTypeMap可能无法识别像flv,mpeg,3gpp,cpp等文件扩展名。 所以你需要考虑如何扩展MimeTypeMap来维护你的代码。 这是一个例子。

http://grepcode.com/file/repo1.maven.org/maven2/com.google.okhttp/okhttp/20120626/libcore/net/MimeUtils.java#MimeUtils

另外,这是一个完整的MIMEtypes列表

http://www.sitepoint.com/web-foundations/mime-types-complete-list/

 get file object.... File file = new File(filePath); then....pass as a parameter to... getMimeType(file); ...here is public String getMimeType(File file) { String mimetype = MimeTypeMap.getSingleton().getMimeTypeFromExtension(MimeTypeMap.getFileExtensionFromUrl(Uri.fromFile(file).toString()).toLowerCase()); if (mimetype == null) { return "*/*"; } return mimetype;///return the mimeType } 

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

从本地文件mime:

 String url = file.getAbsolutePath(); FileNameMap fileNameMap = URLConnection.getFileNameMap(); String mime = fileNameMap.getContentTypeFor("file://"+url); 

你有多种select来获得文件的扩展名,如:1 String filename = uri.getLastPathSegment(); 看到这个链接

2 – 你也可以使用这个代码

  filePath .substring(filePath.lastIndexOf(".")+1); 

但是这并不好。 3 – 如果你有文件的URI,那么使用这个代码

 String[] projection = { MediaStore.MediaColumns.DATA, MediaStore.MediaColumns.MIME_TYPE }; 

4 – 如果您有URL,则使用以下代码:

  public static String getMimeType(String url) { String type = null; String extension = MimeTypeMap.getFileExtensionFromUrl(url); if (extension != null) { type = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension); } return type; } 

享受你的代码:)

 // new processing the mime type out of Uri which may return null in some cases String mimeType = getContentResolver().getType(uri); // old processing the mime type out of path using the extension part if new way returned null if (mimeType == null){mimeType URLConnection.guessContentTypeFromName(path);} 

而从资产/文件(注意,从MimeTypeMap中缺less的情况下)。

 private String getMimeType(String path) { if (null == path) return "*/*"; String extension = path; int lastDot = extension.lastIndexOf('.'); if (lastDot != -1) { extension = extension.substring(lastDot + 1); } // Convert the URI string to lower case to ensure compatibility with MimeTypeMap (see CB-2185). extension = extension.toLowerCase(Locale.getDefault()); if (extension.equals("3ga")) { return "audio/3gpp"; } else if (extension.equals("js")) { return "text/javascript"; } else if (extension.equals("woff")) { return "application/x-font-woff"; } else { // TODO // anyting missing from the map (http://www.sitepoint.com/web-foundations/mime-types-complete-list/) // reference: http://grepcode.com/file/repo1.maven.org/maven2/com.google.okhttp/okhttp/20120626/libcore/net/MimeUtils.java#MimeUtils } return MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension); } 

同时使用ContentResolver

 contentResolver.getType(uri) 

而http / https请求

  try { HttpURLConnection conn = httpClient.open(new URL(uri.toString())); conn.setDoInput(false); conn.setRequestMethod("HEAD"); return conn.getHeaderField("Content-Type"); } catch (IOException e) { } 

我尝试使用标准方法来确定MIMEtypes,但我不能保留使用MimeTypeMap.getFileExtensionFromUrl(uri.getPath())的文件扩展名。 这个方法返回了一个空string。 所以我提出了非平凡的解决scheme来保留文件扩展。

这里是返回文件扩展的方法

 private String getExtention(String fileName){ char[] arrayOfFilename = fileName.toCharArray(); for(int i = arrayOfFilename.length-1; i > 0; i--){ if(arrayOfFilename[i] == '.'){ return fileName.substring(i+1, fileName.length()); } } return ""; } 

并保留文件扩展可能会得到像下面的MIMEtypes

 public String getMimeType(File file) { String mimeType = ""; String extension = getExtention(file.getName()); if (MimeTypeMap.getSingleton().hasExtension(extension)) { mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension); } return mimeType; } 

对于Xamarin Android (从上面的@ HoaLe的回答)

 public String getMimeType(Uri uri) { String mimeType = null; if (uri.Scheme.Equals(ContentResolver.SchemeContent)) { ContentResolver cr = Application.Context.ContentResolver; mimeType = cr.GetType(uri); } else { String fileExtension = MimeTypeMap.GetFileExtensionFromUrl(uri.ToString()); mimeType = MimeTypeMap.Singleton.GetMimeTypeFromExtension( fileExtension.ToLower()); } return mimeType; } 
 public static String getFileType(Uri file) { try { if (file.getScheme().equals(ContentResolver.SCHEME_CONTENT)) return subStringFromLastMark(SystemMaster.getContentResolver().getType(file), "/"); else return MimeTypeMap.getFileExtensionFromUrl(file.toString()).toLowerCase(); } catch(Exception e) { return null; } } public static String getMimeType(Uri file) { try { return MimeTypeMap.getSingleton().getMimeTypeFromExtension(getFileType(file)); } catch(Exception e) { return null; } } public static String subStringFromLastMark(String str,String mark) { int l = str.lastIndexOf(mark); int end = str.length(); if(l == -1) return str; return str.substring(l + 1, end); }