Java:一种将Mime(内容)类型与CommonsMultipartFile的文件扩展名匹配的方法

Asc*_*ian 1 java string comparison

在我的公司,出于其他原因,我需要将mime类型与文件扩展名进行比较。我有一个CommonsMultipartFile。我正在尝试找出进行此比较的最佳方法。我已经看到了MimetypesFileTypeMap,但不确定是否可以在这里使用。我试图避免(或限制)任何硬编码。

我得到这样的值:

CommonsMultipartFile file = ...;
String fileName = file.getOriginalFilename();
String contentType = file.getContentType();

String extension = FilenameUtils.getExtension(fileName);
Run Code Online (Sandbox Code Playgroud)

感谢您的指导和帮助。谢谢!

Luc*_*cas 5

这种情况下的Java库非常有限(类型数)。这是我的方法:

static String getMimeType(String fileName) {
    // 1. first use java's built-in utils
    FileNameMap mimeTypes = URLConnection.getFileNameMap();
    String contentType = mimeTypes.getContentTypeFor(fileName);

    // 2. nothing found -> lookup our in extension map to find types like ".doc" or ".docx"
    if (contentType == null) {
        String extension = fileName.substring(fileName.lastIndexOf('.') + 1, fileName.length());;
        contentType = fileExtensionMap.get(extension);
    }
    return contentType;
}
Run Code Online (Sandbox Code Playgroud)

第2步涉及一张静态地图:

private static final Map<String, String> fileExtensionMap;

static {
    fileExtensionMap = new HashMap<String, String>();
    // MS Office
    fileExtensionMap.put("doc", "application/msword");
    fileExtensionMap.put("dot", "application/msword");
    fileExtensionMap.put("docx", "application/vnd.openxmlformats-officedocument.wordprocessingml.document");
    fileExtensionMap.put("dotx", "application/vnd.openxmlformats-officedocument.wordprocessingml.template");
    fileExtensionMap.put("docm", "application/vnd.ms-word.document.macroEnabled.12");
    fileExtensionMap.put("dotm", "application/vnd.ms-word.template.macroEnabled.12");
    fileExtensionMap.put("xls", "application/vnd.ms-excel");
    fileExtensionMap.put("xlt", "application/vnd.ms-excel");
    fileExtensionMap.put("xla", "application/vnd.ms-excel");
    fileExtensionMap.put("xlsx", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
    fileExtensionMap.put("xltx", "application/vnd.openxmlformats-officedocument.spreadsheetml.template");
    fileExtensionMap.put("xlsm", "application/vnd.ms-excel.sheet.macroEnabled.12");
    fileExtensionMap.put("xltm", "application/vnd.ms-excel.template.macroEnabled.12");
    fileExtensionMap.put("xlam", "application/vnd.ms-excel.addin.macroEnabled.12");
    fileExtensionMap.put("xlsb", "application/vnd.ms-excel.sheet.binary.macroEnabled.12");
    fileExtensionMap.put("ppt", "application/vnd.ms-powerpoint");
    fileExtensionMap.put("pot", "application/vnd.ms-powerpoint");
    fileExtensionMap.put("pps", "application/vnd.ms-powerpoint");
    fileExtensionMap.put("ppa", "application/vnd.ms-powerpoint");
    fileExtensionMap.put("pptx", "application/vnd.openxmlformats-officedocument.presentationml.presentation");
    fileExtensionMap.put("potx", "application/vnd.openxmlformats-officedocument.presentationml.template");
    fileExtensionMap.put("ppsx", "application/vnd.openxmlformats-officedocument.presentationml.slideshow");
    fileExtensionMap.put("ppam", "application/vnd.ms-powerpoint.addin.macroEnabled.12");
    fileExtensionMap.put("pptm", "application/vnd.ms-powerpoint.presentation.macroEnabled.12");
    fileExtensionMap.put("potm", "application/vnd.ms-powerpoint.presentation.macroEnabled.12");
    fileExtensionMap.put("ppsm", "application/vnd.ms-powerpoint.slideshow.macroEnabled.12");
    // Open Office
    fileExtensionMap.put("odt", "application/vnd.oasis.opendocument.text");
    fileExtensionMap.put("ott", "application/vnd.oasis.opendocument.text-template");
    fileExtensionMap.put("oth", "application/vnd.oasis.opendocument.text-web");
    fileExtensionMap.put("odm", "application/vnd.oasis.opendocument.text-master");
    fileExtensionMap.put("odg", "application/vnd.oasis.opendocument.graphics");
    fileExtensionMap.put("otg", "application/vnd.oasis.opendocument.graphics-template");
    fileExtensionMap.put("odp", "application/vnd.oasis.opendocument.presentation");
    fileExtensionMap.put("otp", "application/vnd.oasis.opendocument.presentation-template");
    fileExtensionMap.put("ods", "application/vnd.oasis.opendocument.spreadsheet");
    fileExtensionMap.put("ots", "application/vnd.oasis.opendocument.spreadsheet-template");
    fileExtensionMap.put("odc", "application/vnd.oasis.opendocument.chart");
    fileExtensionMap.put("odf", "application/vnd.oasis.opendocument.formula");
    fileExtensionMap.put("odb", "application/vnd.oasis.opendocument.database");
    fileExtensionMap.put("odi", "application/vnd.oasis.opendocument.image");
    fileExtensionMap.put("oxt", "application/vnd.openofficeorg.extension");
    // Other
    fileExtensionMap.put("txt", "text/plain");
    fileExtensionMap.put("rtf", "application/rtf");
    fileExtensionMap.put("pdf", "application/pdf");
}
Run Code Online (Sandbox Code Playgroud)

对我来说效果很好,希望对您有所帮助!


VGR*_*VGR 5

最可靠的方法是使用Files.probeContentType,但这需要一个实际的文件,部分原因是并非所有操作系统都依赖扩展名来确定文件类型。

\n\n

在 Linux 中,下一个最佳方法是new MimetypesFileTypeMap("/etc/mime.types"),它将真正基于系统的映射。我不知道 OS X 是否有一个mime.types文件(尽管搜索显示CUPS for OS X 使用这样的文件,具有增强但主要向后兼容的语法)。

\n\n

据我所知,Windows 中没有内置的 Java 类用于获取 MIME-type\xe2\x86\x94extension 映射。

\n\n

URLConnection.getFileNameMap()返回一个具有相当数量条目的 FileNameMap,但仍然不基于系统的映射。例如,在我的 Linux 系统上,它为 .bz2 和 .rpm 文件返回 null。

\n\n

FileTypeMap.getDefaultFileTypeMap()似乎有一些条目,但它显然也不是基于系统的映射。至少在我的系统上,它为 .png 文件返回“application/octet-stream”。

\n\n

我认为最简单的事情是将它们全部封装在一个类中:

\n\n
import java.io.IOException;\nimport java.nio.file.Files;\nimport java.nio.file.Path;\nimport java.nio.file.Paths;\nimport java.net.FileNameMap;\nimport java.net.URLConnection;\nimport java.util.logging.Logger;\nimport java.util.logging.Level;\nimport javax.activation.FileTypeMap;\nimport javax.activation.MimetypesFileTypeMap;\n\npublic class MimeTypes {\n\n    private static final Logger logger =\n        Logger.getLogger(MimeTypes.class.getName());\n\n    private static final String DEFAULT_TYPE = "application/octet-stream";\n\n    private static final Path mimeTypesFile = Paths.get("/etc/mime.types");\n\n    private final FileNameMap fileNameMap = URLConnection.getFileNameMap();\n\n    private final FileTypeMap fileTypeMap = FileTypeMap.getDefaultFileTypeMap();\n\n    private final FileTypeMap mimeTypesMap;\n\n    public MimeTypes() {\n        FileTypeMap map = null;\n        if (Files.isRegularFile(mimeTypesFile)) {\n            try {\n                map = new MimetypesFileTypeMap(mimeTypesFile.toString());\n            } catch (IOException e) {\n                logger.log(Level.WARNING, "Couldn\'t read " + mimeTypesFile, e);\n            }\n        }\n        mimeTypesMap = map;\n    }\n\n    public String getContentType(String filename) {\n        String type = null;\n\n        if (mimeTypesMap != null) {\n            type = mimeTypesMap.getContentType(filename);\n        }\n\n        if (type == null || type.equals(DEFAULT_TYPE)) {\n            type = fileNameMap.getContentTypeFor(filename);\n        }\n\n        if (type == null || type.equals(DEFAULT_TYPE)) {\n            type = fileTypeMap.getContentType(filename);\n        }\n\n        return type;\n    }\n\n    public static void main(String[] args) {\n\n        MimeTypes mimeTypes = new MimeTypes();\n\n        for (String arg : args) {\n            System.out.printf("Type of file \\"%s\\" is \\"%s\\"%n",\n                arg, mimeTypes.getContentType(arg));\n        }\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

这会给你带来相当好的结果。如果你想在 Windows 中进行真正的基于平台的 MIME 类型检查,我知道的唯一方法是读取注册表:

\n\n
import java.io.IOException;\nimport java.nio.file.Files;\nimport java.nio.file.Path;\nimport java.nio.file.Paths;\nimport java.net.FileNameMap;\nimport java.net.URLConnection;\nimport java.util.logging.Logger;\nimport java.util.logging.Level;\nimport javax.activation.FileTypeMap;\nimport javax.activation.MimetypesFileTypeMap;\n\nimport java.io.File;\nimport java.io.BufferedReader;\nimport java.io.BufferedWriter;\nimport java.io.InputStreamReader;\nimport java.io.OutputStreamWriter;\n\nimport java.util.Arrays;\nimport java.util.ArrayList;\nimport java.util.Map;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Collections;\nimport java.util.Formatter;\n\nimport java.util.concurrent.Callable;\nimport java.util.concurrent.Executors;\nimport java.util.concurrent.ExecutorService;\nimport java.util.concurrent.Future;\nimport java.util.concurrent.TimeUnit;\nimport java.util.concurrent.ExecutionException;\n\npublic class MimeTypes {\n\n    private static final Logger logger =\n        Logger.getLogger(MimeTypes.class.getName());\n\n    private static final String DEFAULT_TYPE = "application/octet-stream";\n\n    private static final Path mimeTypesFile = Paths.get("/etc/mime.types");\n\n    private final FileNameMap fileNameMap = URLConnection.getFileNameMap();\n\n    private final FileTypeMap fileTypeMap = FileTypeMap.getDefaultFileTypeMap();\n\n    private final FileTypeMap mimeTypesMap;\n\n    public MimeTypes() {\n        FileTypeMap map = null;\n\n        if (Files.isRegularFile(mimeTypesFile)) {\n            try {\n                map = new MimetypesFileTypeMap(mimeTypesFile.toString());\n            } catch (IOException e) {\n                logger.log(Level.WARNING, "Couldn\'t read " + mimeTypesFile, e);\n            }\n        }\n\n        if (map == null && System.getProperty("os.name").contains("Windows")) {\n            try {\n                map = new WindowsFileTypeMap();\n            } catch (IOException e) {\n                logger.log(Level.WARNING, "Couldn\'t read registered types", e);\n            } catch (InterruptedException e) {\n                logger.log(Level.INFO, "Interrupted; read canceled", e);\n            }\n        }\n\n        mimeTypesMap = map;\n    }\n\n    public String getContentType(String filename) {\n        String type = null;\n\n        if (mimeTypesMap != null) {\n            type = mimeTypesMap.getContentType(filename);\n        }\n\n        if (type == null || type.equals(DEFAULT_TYPE)) {\n            type = fileNameMap.getContentTypeFor(filename);\n        }\n\n        if (type == null || type.equals(DEFAULT_TYPE)) {\n            type = fileTypeMap.getContentType(filename);\n        }\n\n        return type;\n    }\n\n    private static class WindowsFileTypeMap\n    extends FileTypeMap {\n\n        private final Map<String, String> extensionToMimeType;\n\n        public WindowsFileTypeMap()\n        throws IOException,\n               InterruptedException {\n\n            ProcessBuilder builder =\n                new ProcessBuilder("PowerShell.exe", "-Command", "-");\n\n            Process process = builder.start();\n            List<String> regEntryNames = getOutput(process, String.format(\n                "Get-ChildItem \\"Registry::HKEY_CLASSES_ROOT\\\\\\" |"\n                    + " Select-String -InputObject { $_.Name }"\n                    + " -SimpleMatch -Pattern \\"HKEY_CLASSES_ROOT\\\\.\\"%n"));\n\n            Formatter input = new Formatter();\n            for (String name : regEntryNames) {\n                input.format(\n                    "$values = Get-ItemProperty \\"Registry::%s\\"%n" +\n                    "$values.\\"Content Type\\" + \\" \\"%n", name);\n            }\n\n            process = builder.start();\n            List<String> mimeTypes = getOutput(process, input.toString());\n\n            int len = regEntryNames.size();\n            extensionToMimeType = new HashMap<>(len);\n            for (int i = 0; i < len; i++) {\n                String mimeType = mimeTypes.get(i).trim();\n                if (!mimeType.isEmpty()) {\n                    String extension =\n                        regEntryNames.get(i).replace("HKEY_CLASSES_ROOT\\\\", "");\n                    extensionToMimeType.put(extension, mimeType);\n                }\n            }\n        }\n\n        @Override\n        public String getContentType(File file) {\n            return getContentType(file.toString());\n        }\n\n        @Override\n        public String getContentType(String filename) {\n            int period = filename.lastIndexOf(\'.\');\n            if (period < 0) {\n                return DEFAULT_TYPE;\n            }\n\n            String ext = filename.substring(period);\n            String type = extensionToMimeType.get(ext);\n            return (type != null ? type : DEFAULT_TYPE);\n        }\n\n        private static List<String> getOutput(final Process process,\n                                              final String input)\n        throws IOException,\n               InterruptedException {\n\n            Callable<Void> inputSender = new Callable<Void>() {\n                @Override\n                public Void call()\n                throws IOException {\n                    try (BufferedWriter writer =\n                        new BufferedWriter(\n                            new OutputStreamWriter(\n                                process.getOutputStream()))) {\n                        writer.write(input);\n                    }\n                    return null;\n                }\n            };\n\n            ExecutorService executor = Executors.newSingleThreadExecutor();\n            Future<?> inputSenderStatus = executor.submit(inputSender);\n\n            List<String> lines;\n            try (BufferedReader reader =\n                new BufferedReader(\n                    new InputStreamReader(\n                        process.getInputStream()))) {\n                lines = new ArrayList<>();\n                String line;\n                while ((line = reader.readLine()) != null) {\n                    lines.add(line);\n                }\n            }\n\n            try {\n                inputSenderStatus.get();\n            } catch (ExecutionException e) {\n                throw new IOException(e);\n            }\n\n            executor.shutdown();\n            executor.awaitTermination(30, TimeUnit.SECONDS);\n\n            process.waitFor();\n\n            return lines;\n        }\n    }\n\n    public static void main(String[] args) {\n\n        MimeTypes mimeTypes = new MimeTypes();\n\n        for (String arg : args) {\n            System.out.printf("Type of file \\"%s\\" is \\"%s\\"%n",\n                arg, mimeTypes.getContentType(arg));\n        }\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n