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

时间:2014-12-10 14:03:30

标签: java string comparison

在我公司,我需要将mime类型与文件扩展名进行比较,原因更多。我有CommonsMultipartFile。我试图找出做这种比较的最佳方法。我见过MimetypesFileTypeMap,但不确定这是否可行。我试图避免(或限制)任何硬编码。

我得到了这样的值:

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

String extension = FilenameUtils.getExtension(fileName);

我感谢任何指导和帮助。谢谢!

4 个答案:

答案 0 :(得分:4)

该案例的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;
}

第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");
}

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

答案 1 :(得分:4)

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

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

据我所知,没有内置的Java类可以在Windows中获取MIME-type↔extension映射。

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

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

我认为最简单的方法是将所有这些内容封装在一个类中:

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.net.FileNameMap;
import java.net.URLConnection;
import java.util.logging.Logger;
import java.util.logging.Level;
import javax.activation.FileTypeMap;
import javax.activation.MimetypesFileTypeMap;

public class MimeTypes {

    private static final Logger logger =
        Logger.getLogger(MimeTypes.class.getName());

    private static final String DEFAULT_TYPE = "application/octet-stream";

    private static final Path mimeTypesFile = Paths.get("/etc/mime.types");

    private final FileNameMap fileNameMap = URLConnection.getFileNameMap();

    private final FileTypeMap fileTypeMap = FileTypeMap.getDefaultFileTypeMap();

    private final FileTypeMap mimeTypesMap;

    public MimeTypes() {
        FileTypeMap map = null;
        if (Files.isRegularFile(mimeTypesFile)) {
            try {
                map = new MimetypesFileTypeMap(mimeTypesFile.toString());
            } catch (IOException e) {
                logger.log(Level.WARNING, "Couldn't read " + mimeTypesFile, e);
            }
        }
        mimeTypesMap = map;
    }

    public String getContentType(String filename) {
        String type = null;

        if (mimeTypesMap != null) {
            type = mimeTypesMap.getContentType(filename);
        }

        if (type == null || type.equals(DEFAULT_TYPE)) {
            type = fileNameMap.getContentTypeFor(filename);
        }

        if (type == null || type.equals(DEFAULT_TYPE)) {
            type = fileTypeMap.getContentType(filename);
        }

        return type;
    }

    public static void main(String[] args) {

        MimeTypes mimeTypes = new MimeTypes();

        for (String arg : args) {
            System.out.printf("Type of file \"%s\" is \"%s\"%n",
                arg, mimeTypes.getContentType(arg));
        }
    }
}

这将为您带来相当不错的结果。如果你想在Windows中进行真正的基于平台的MIME类型检查,我知道这样做的唯一方法是阅读注册表:

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.net.FileNameMap;
import java.net.URLConnection;
import java.util.logging.Logger;
import java.util.logging.Level;
import javax.activation.FileTypeMap;
import javax.activation.MimetypesFileTypeMap;

import java.io.File;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;

import java.util.Arrays;
import java.util.ArrayList;
import java.util.Map;
import java.util.HashMap;
import java.util.List;
import java.util.Collections;
import java.util.Formatter;

import java.util.concurrent.Callable;
import java.util.concurrent.Executors;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.ExecutionException;

public class MimeTypes {

    private static final Logger logger =
        Logger.getLogger(MimeTypes.class.getName());

    private static final String DEFAULT_TYPE = "application/octet-stream";

    private static final Path mimeTypesFile = Paths.get("/etc/mime.types");

    private final FileNameMap fileNameMap = URLConnection.getFileNameMap();

    private final FileTypeMap fileTypeMap = FileTypeMap.getDefaultFileTypeMap();

    private final FileTypeMap mimeTypesMap;

    public MimeTypes() {
        FileTypeMap map = null;

        if (Files.isRegularFile(mimeTypesFile)) {
            try {
                map = new MimetypesFileTypeMap(mimeTypesFile.toString());
            } catch (IOException e) {
                logger.log(Level.WARNING, "Couldn't read " + mimeTypesFile, e);
            }
        }

        if (map == null && System.getProperty("os.name").contains("Windows")) {
            try {
                map = new WindowsFileTypeMap();
            } catch (IOException e) {
                logger.log(Level.WARNING, "Couldn't read registered types", e);
            } catch (InterruptedException e) {
                logger.log(Level.INFO, "Interrupted; read canceled", e);
            }
        }

        mimeTypesMap = map;
    }

    public String getContentType(String filename) {
        String type = null;

        if (mimeTypesMap != null) {
            type = mimeTypesMap.getContentType(filename);
        }

        if (type == null || type.equals(DEFAULT_TYPE)) {
            type = fileNameMap.getContentTypeFor(filename);
        }

        if (type == null || type.equals(DEFAULT_TYPE)) {
            type = fileTypeMap.getContentType(filename);
        }

        return type;
    }

    private static class WindowsFileTypeMap
    extends FileTypeMap {

        private final Map<String, String> extensionToMimeType;

        public WindowsFileTypeMap()
        throws IOException,
               InterruptedException {

            ProcessBuilder builder =
                new ProcessBuilder("PowerShell.exe", "-Command", "-");

            Process process = builder.start();
            List<String> regEntryNames = getOutput(process, String.format(
                "Get-ChildItem \"Registry::HKEY_CLASSES_ROOT\\\" |"
                    + " Select-String -InputObject { $_.Name }"
                    + " -SimpleMatch -Pattern \"HKEY_CLASSES_ROOT\\.\"%n"));

            Formatter input = new Formatter();
            for (String name : regEntryNames) {
                input.format(
                    "$values = Get-ItemProperty \"Registry::%s\"%n" +
                    "$values.\"Content Type\" + \" \"%n", name);
            }

            process = builder.start();
            List<String> mimeTypes = getOutput(process, input.toString());

            int len = regEntryNames.size();
            extensionToMimeType = new HashMap<>(len);
            for (int i = 0; i < len; i++) {
                String mimeType = mimeTypes.get(i).trim();
                if (!mimeType.isEmpty()) {
                    String extension =
                        regEntryNames.get(i).replace("HKEY_CLASSES_ROOT\\", "");
                    extensionToMimeType.put(extension, mimeType);
                }
            }
        }

        @Override
        public String getContentType(File file) {
            return getContentType(file.toString());
        }

        @Override
        public String getContentType(String filename) {
            int period = filename.lastIndexOf('.');
            if (period < 0) {
                return DEFAULT_TYPE;
            }

            String ext = filename.substring(period);
            String type = extensionToMimeType.get(ext);
            return (type != null ? type : DEFAULT_TYPE);
        }

        private static List<String> getOutput(final Process process,
                                              final String input)
        throws IOException,
               InterruptedException {

            Callable<Void> inputSender = new Callable<Void>() {
                @Override
                public Void call()
                throws IOException {
                    try (BufferedWriter writer =
                        new BufferedWriter(
                            new OutputStreamWriter(
                                process.getOutputStream()))) {
                        writer.write(input);
                    }
                    return null;
                }
            };

            ExecutorService executor = Executors.newSingleThreadExecutor();
            Future<?> inputSenderStatus = executor.submit(inputSender);

            List<String> lines;
            try (BufferedReader reader =
                new BufferedReader(
                    new InputStreamReader(
                        process.getInputStream()))) {
                lines = new ArrayList<>();
                String line;
                while ((line = reader.readLine()) != null) {
                    lines.add(line);
                }
            }

            try {
                inputSenderStatus.get();
            } catch (ExecutionException e) {
                throw new IOException(e);
            }

            executor.shutdown();
            executor.awaitTermination(30, TimeUnit.SECONDS);

            process.waitFor();

            return lines;
        }
    }

    public static void main(String[] args) {

        MimeTypes mimeTypes = new MimeTypes();

        for (String arg : args) {
            System.out.printf("Type of file \"%s\" is \"%s\"%n",
                arg, mimeTypes.getContentType(arg));
        }
    }
}

答案 2 :(得分:3)

我有一个课程https://github.com/nablex/utils-io/blob/master/src/main/java/be/nabu/utils/io/ContentTypeMap.java可以做到这一点。

它添加了一些在URLConnection中缺少的东西:

  • 它可以在两个方向上处理1- *关系(一个mime类型,多个扩展,反之亦然)
  • 你可以双向(mimetype&gt;扩展名和扩展名&gt; mimetype)

此外,可以使用以下方法将其插入URLConnection:

ContentTypeMap.register()

默认情况下,它使用文件加载映射:https://github.com/nablex/utils-io/blob/master/src/main/resources/mime.properties

答案 3 :(得分:0)

boolean getMimeType(String fileName) {
boolean flag=false;
Map<String, String> fileExtnMap= new HashMap<String, String>();
fileExtnMap.put("jpg","image/jpg");
fileExtnMap.put("jpeg","image/jpeg");
fileExtnMap.put("pdf","application/pdf");

FileNameMap fileMap = URLConnection.getFileNameMap();
String contentType=fileMap .getContentTypeFor(fileName);
String[] extn= fileName.split("\\.");
contentType = fileExtnMap.get(extn[1]);
if(extn[1].equals("pdf") && contentType.equals("application/pdf") || extn[1].equals("jpg") && contentType.equals("image/jpg") || extn[1].equals("jpeg") && contentType.equals("image/jpeg")){
    flag=true;
}
    
    return flag;
}