Spring Upload File 报错FileNotFoundException
环境:
Springboot2.0.4JDK1.8内嵌 Apache Tomcat/8.5.32
1、前端代码
前端上传网页表单,enctype 和 input 的type=file 即可,使用单文件上传举例:
图片
2、后端代码
@RestController
@RequestMapping("/file")public classUploadFileController {
@Value("${file.upload.path}")private String path = "upload/";
@RequestMapping(value= "fileUpload", method =RequestMethod.POST)
@ResponseBodypublic String fileUpload(@RequestParam("file") MultipartFile file) {if(file.isEmpty()) {return "false";
}
String fileName=file.getOriginalFilename();
File saveFile= new File(path + "/" +fileName);if (!saveFile.getParentFile().exists()) {
saveFile.getParentFile().mkdirs();
}try{
file.transferTo(saveFile);//保存文件
return "true";
}catch(Exception e) {
e.printStackTrace();return "false";
}
}
}
3、问题分析与解决
按照上面配置运行时,在保存文件 file.transferTo(saveFile) 报错
3.1 问题原因分析:
saveFile是相对路径,指向 upload/doc20170816162034_001.jpg
file.transferTo 方法调用时,判断如果是相对路径,则使用temp目录,为父目录
因此,实际保存位置为 C:\Users\xxxx\AppData\Local\Temp\tomcat.372873030384525225.8080\work\Tomcat\localhost\ROOT\upload\doc20170816162034_001.jpg
一则,位置不对,二则没有父目录存在,因此产生上述错误。
3.2 问题解决
transferTo 传入参数 定义为绝对路径
@RestController
@RequestMapping("/file")public classUploadFileController {
@Value("${file.upload.path}")private String path = "upload/";
@RequestMapping(value= "fileUpload", method =RequestMethod.POST)
@ResponseBodypublic String fileUpload(@RequestParam("file") MultipartFile file) {if(file.isEmpty()) {return "false";
}
String fileName=file.getOriginalFilename();
File dest= new File(new File(path).getAbsolutePath()+ "/" +fileName);if (!dest.getParentFile().exists()) {
dest.getParentFile().mkdirs();
}try{
file.transferTo(dest);//保存文件
return "true";
}catch(Exception e) {
e.printStackTrace();return "false";
}
}
}
也可以 file.getBytes() 获得字节数组,OutputStream.write(byte[] bytes)自己写到输出流中。
4、补充方法
application.properties 中增加配置项
spring.servlet.multipart.location= # Intermediate location of uploaded files.
关于上传文件的访问
增加一个自定义的ResourceHandler把目录公布出去
//写一个Java Config
@Configurationpublic class webMvcConfig implementsorg.springframework.web.servlet.config.annotation.WebMvcConfigurer{//定义在application.properties
@Value("${file.upload.path}")private String path = "upload/";public voidaddResourceHandlers(ResourceHandlerRegistry registry) {
String p= new File(path).getAbsolutePath() + File.separator;//取得在服务器中的绝对路径
System.out.println("Mapping /upload/** from " +p);
registry.addResourceHandler("/upload/**") //外部访问地址
.addResourceLocations("file:" + p)//springboot需要增加file协议前缀
.setCacheControl(CacheControl.maxAge(30, TimeUnit.MINUTES));//设置浏览器缓存30分钟
}
}
application.properties 中 file.upload.path=upload/
实际存储目录
D:/upload/2019/03081625111.jpg
访问地址(假设应用发布在http://www.a.com/)
http://www.a.com/upload/2019/03081625111.jpg
在Controller中增加一个RequestMapping,把文件输出到输出流中
@RestController
@RequestMapping("/file")public classUploadFileController {
@AutowiredprotectedHttpServletRequest request;
@AutowiredprotectedHttpServletResponse response;
@AutowiredprotectedConversionService conversionService;
@Value("${file.upload.path}")private String path = "upload/";
@RequestMapping(value="/view", method =RequestMethod.GET)public Object view(@RequestParam("id") Integer id){//通常上传的文件会有一个数据表来存储,这里返回的id是记录id
UploadFile file = conversionService.convert(id, UploadFile.class);//这步也可以写在请求参数中
if(file==null){throw new RuntimeException("没有文件");
}
File source= new File(new File(path).getAbsolutePath()+ "/" +file.getPath());
response.setContentType(contentType);try{
FileCopyUtils.copy(newFileInputStream(source), response.getOutputStream());
}catch(Exception e) {
e.printStackTrace();
}return null;
}
}