之前写了一篇博文关于multiple标签简单使用的文章,在回复网友问题关于IE11浏览器支持时,发现程序在IE11和Edge浏览器下报错
java.io.IOException: java.io.FileNotFoundException: D:\DEV_ENV\upload\C:\Users\PC\Downloads\团险业务概念与特点.ppt (文件名、目录名或卷标语法不正确。)
错误信息很明显,程序找不到“D:\DEV_ENV\upload\C:\Users\PC\Downloads\团险业务概念与特点.ppt” 这个文件
细看一眼,好像有问题,这个文件的路径有错,前面是带有盘符的路径信息,后面又有盘符的路径信息
查看代码后,发现问题的症结
/**
* 文件保存方法
* @param file
* @param destination
* @throws IOException
* @throws IllegalStateException
*/
private void saveFile(MultipartFile file, String destination) throws IllegalStateException, IOException {
// 获取上传的文件名称,并结合存放路径,构建新的文件名称
String filename = file.getOriginalFilename();
File filepath = new File(destination, filename);
// 判断路径是否存在,不存在则新创建一个
if (!filepath.getParentFile().exists()) {
filepath.getParentFile().mkdirs();
}
// 将上传文件保存到目标文件目录
file.transferTo(new File(destination + File.separator + filename));
}
代码中file.getOriginalFilename() 获取上传的文件名称,但是在IE11/Edge浏览器下面,获取到的路径信息带有盘符
查看该方法定义
/**
* Return the original filename in the client's filesystem.
* <p>This may contain path information depending on the browser used,
* but it typically will not with any other than Opera.
* @return the original filename, or the empty String if no file has been chosen
* in the multipart form, or {@code null} if not defined or not available
* @see org.apache.commons.fileupload.FileItem#getName()
* @see org.springframework.web.multipart.commons.CommonsMultipartFile#setPreserveFilename
*/
@Nullable
String getOriginalFilename();
最上面两句含义便是,该方法返回文件在客户端文件系统中的原始文件名称,该名称或许会包含路径信息,这点依赖于浏览器。
由于之前的测试都是在Chrome浏览器,未测试IE11浏览器,故未发现该问题。
修复该问题,在代码中增加浏览器的判断
// 获取上传的文件名称,并结合存放路径,构建新的文件名称
String filename = file.getOriginalFilename();
// 文件上传时,Chrome和IE/Edge对于originalFilename处理不同
// Chrome 会获取到该文件的直接文件名称,IE/Edge会获取到文件上传时完整路径/文件名
// Check for Unix-style path
int unixSep = filename.lastIndexOf('/');
// Check for Windows-style path
int winSep = filename.lastIndexOf('\\');
// Cut off at latest possible point
int pos = (winSep > unixSep ? winSep : unixSep);
if (pos != -1) {
// Any sort of path separator found...
filename = filename.substring(pos + 1);
}
File filepath = new File(destination, filename);
这段系统路径分隔符的判断,来自于org.springframework.web.multipart.commons.CommonsMultipartFile类的getOriginalFilename() 方法内。增加后,若为带有路径的文件名信息,则截取我们实际需要的文件名信息。
修改后,测试上传无误,这里就不贴测试信息了。