如何确定在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来维护你的代码。 这是一个例子。
另外,这是一个完整的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); }