慎用URLConnection.guessContentTypeFromStream推断文件mime类型
程序员文章站
2022-07-12 11:15:13
...
在项目中有这么一个需求:判断上传文件的类型,考虑两种方案:
1. 通过正则表达式从文件名中获取;
2. 使用URLConnection.guessContentTypeFromStream通过文件前16个字节推断;
第一种方法显然不够严谨(文件名可随意更改),于是采用 了第二种方案
// some code FileInputStream inputFile = new FileInputStream("D:/test.pdf"); String mime = URLConnection.guessContentTypeFromStream(inputFile); // save to mongodb......
一周后,偶然发现所有上传的文件在mongo中mine字段均为空,翻读guessContentTypeFromStream方法源码有一处判断引起了我的注意:
markSupported ? 似有所悟,翻阅JDK文档后一切拨云见日:
markSupported public boolean markSupported() Tests if this input stream supports the mark and reset methods. Whether or not mark and reset are supported is an invariant property of a particular input stream instance. The markSupported method of InputStream returns false. Returns: true if this stream instance supports the mark and reset methods; false otherwise. See Also: mark(int), reset()
首先介绍一下InputStream类提供的mark与reset方法:
在该输入流中使用mark标记当前位置,后续调用 reset 方法重新将流定位于最后标记位置,以便后续读取。
markSupported方法可以判断当前类是否具有mark与reset方法的能力,只有重写了mark与reset方法,markSupported才会返回true。前面展示的代码使用的FileInputStream没有重写父类InputStream的这两个方法,其不具有mark和reset方法的能力,使用BufferInputStream替换FileInputStream可解决此问题:
FileInputStream inputFile = new FileInputStream("D:/t1.png"); System.out.println("FileInputStream mime:" + URLConnection.guessContentTypeFromStream(inputFile)); System.out.println("BufferedInputStream mime:" + URLConnection.guessContentTypeFromStream(new BufferedInputStream(inputFile))); print result: FileInputStream mime:null BufferedInputStream mime:image/png