我们的应用程序使用Commons VFS读取各种类型的文件。我们使用VFS提供的自动文件类型检测,通过它的文件扩展名映射。
问题:VFS错误地分类gz文件(即。以".gz
"结尾的文件为常规文件,而不是GZIP文件。这可以防止我们使用VFS读取(解压缩的)gz文件的内容,而不需要一些特殊情况的手动破解。
我已经将问题追溯到org.apache.commons.vfs2.impl.FileContentInfoFilenameFactory.create()
,它调用
FileNameMap fileNameMap = URLConnection.getFileNameMap();
contentType = fileNameMap.getContentTypeFor(name);
从当前Java安装中加载文件content-types.properties
。这个文件(至少在Windows上)包含这个映射:
application/octet-stream:
description=Generic Binary Stream;
file_extensions=.saveme,.dump,.hqx,.arc,.obj,.lib,.bin,.exe,.zip,.gz
根据源代码,org.apache.commons.vfs2.impl.FileTypeMap
允许这个映射优先于配置VFS的文件扩展名映射。
有没有人能想到一种方法:(a)扩展一类或两个VFS来解决这个问题,或者(b)配置VFS和/或Java本身,以便VFS正确分类gz文件?
创建如下类,覆盖FileNameMap
的getContentTypeFor
方法,并排除麻烦的application/octet-stream
条目:
public static class MyFileNameMap implements FileNameMap
{
private FileNameMap delegate = URLConnection.getFileNameMap();
@Override
public String getContentTypeFor( String fileName )
{
String contentType = delegate.getContentTypeFor( fileName );
if( "application/octet-stream".equals( contentType ) )
{
// Sun's java classifies zip and gzip as application/octet-stream,
// which VFS then uses, instead of looking at its extension
// map for a more specific mime type
return null;
}
return contentType;
}
}
安装新类:
URLConnection.setFileNameMap( new MyFileNameMap() );
现在当您调用FileSystemManager.resolveFile()
时,VFS将通过返回其扩展映射来为gz
文件选择正确的文件类型。
注意:这是对当前JVM的一个全局更改,所以如果您正在使用任何其他代码,需要将此mime类型条目用于.exe
文件等内容,请小心。