Solve the problem of MultipartFile. transferTo of dest reporting FileNotFoundExcep
- 2021-10-15 10:39:46
- OfStack
Spring Upload file Error FileNotFoundException
Environment:
Springboot 2.0.4 JDK8 Embedded Apache Tomcat/8. 5.32Form, type=file of enctype and input is enough, and the example is uploaded by single file
<form enctype="multipart/form-data" method="POST"
action="/file/fileUpload">
Picture <input type="file" name="file" />
<input type="submit" value=" Upload " />
</form>
@Controller
@RequestMapping("/file")
public class UploadFileController {
@Value("${file.upload.path}")
private String path = "upload/";
@RequestMapping(value = "fileUpload", method = RequestMethod.POST)
@ResponseBody
public String fileUpload(@RequestParam("file") MultipartFile file) {
if (file.isEmpty()) {
return "false";
}
String fileName = file.getOriginalFilename();
File dest = new File(path + "/" + fileName);
if (!dest.getParentFile().exists()) {
dest.getParentFile().mkdirs();
}
try {
file.transferTo(dest); // Save a file
return "true";
} catch (Exception e) {
e.printStackTrace();
return "false";
}
}
}
Running in the save file file. transferTo (dest) reports an error
Problem
dest is a relative path pointing to upload/doc20170816162034_001. jpg
When the file. transferTo method is called, it is judged that if it is a relative path, the temp directory is used as the parent directory
Therefore, the actual save location is C:\ Users\ xxxx\ AppData\ Temp\ tomcat.372873030384525225.8080\ work\ Tomcat\ localhost\ ROOT\ upload\ doc20170816162034_001.jpg
1, the location is wrong, and 2, there is no parent directory, so the above error occurs.
Solution
transferTo incoming parameters are defined as absolute paths
@Controller
@RequestMapping("/file")
public class UploadFileController {
@Value("${file.upload.path}")
private String path = "upload/";
@RequestMapping(value = "fileUpload", method = RequestMethod.POST)
@ResponseBody
public 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); // Save a file
return "true";
} catch (Exception e) {
e.printStackTrace();
return "false";
}
}
}
Alternatively, file. getBytes () gets the byte array and OutputStream. write (byte [] bytes) writes itself to the output stream.
Supplementary method
Adding configuration item in application. properties
spring.servlet.multipart.location= # Intermediate location of uploaded files.
Access to uploaded files
1. Add a custom ResourceHandler to publish the directory
// Write 1 A Java Config
@Configuration
public class webMvcConfig implements org.springframework.web.servlet.config.annotation.WebMvcConfigurer{
// Defined in application.properties
@Value("${file.upload.path}")
private String path = "upload/";
public void addResourceHandlers(ResourceHandlerRegistry registry) {
String p = new File(path).getAbsolutePath() + File.separator;// Gets the absolute path in the server
System.out.println("Mapping /upload/** from " + p);
registry.addResourceHandler("/upload/**") // External access address
.addResourceLocations("file:" + p)// springboot Need to increase file Protocol prefix
.setCacheControl(CacheControl.maxAge(30, TimeUnit.MINUTES));// Setting Browser Cache 30 Minutes
}
}
file. upload. path=upload/in application. properties
Actual storage directory
D:/upload/2019/03081625111.jpg
Access address (assuming the application is published at http://www.a.com/)
http://www.a.com/upload/2019/03081625111.jpg
2. Add an RequestMapping to Controller and output the file to the output stream
@RestController
@RequestMapping("/file")
public class UploadFileController {
@Autowired
protected HttpServletRequest request;
@Autowired
protected HttpServletResponse response;
@Autowired
protected ConversionService conversionService;
@Value("${file.upload.path}")
private String path = "upload/";
@RequestMapping(value="/view", method = RequestMethod.GET)
public Object view(@RequestParam("id") Integer id){
// Usually uploaded files will have 1 Data tables are stored, and the returned id It's a record id
UploadFile file = conversionService.convert(id, UploadFile.class);// This step can also be written in the request parameters
if(file==null){
throw new RuntimeException(" No files ");
}
File source= new File(new File(path).getAbsolutePath()+ "/" + file.getPath());
response.setContentType(contentType);
try {
FileCopyUtils.copy(new FileInputStream(source), response.getOutputStream());
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
MultipartFile. transferTo (dest) File not found
Today, using transferTo this method to upload files, we found some problems in 1 path and found the problem in 1 record
Front-end upload web pages, using a single file upload method
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
</head>
<body>
<form enctype="multipart/form-data" method="post" action="/upload">
Documents: <input type="file" name="head_img">
Name: <input type="text" name="name">
<input type="submit" value=" Upload ">
</form>
</body>
</html>
Background web page
@Controller
@RequestMapping("/file")
public class UploadFileController {
@Value("${file.upload.path}")
private String path = "upload/";
@RequestMapping(value = "fileUpload", method = RequestMethod.POST)
@ResponseBody
public String fileUpload(@RequestParam("file") MultipartFile file) {
if (file.isEmpty()) {
return "false";
}
String fileName = file.getOriginalFilename();
File dest = new File(path + "/" + fileName);
if (!dest.getParentFile().exists()) {
dest.getParentFile().mkdirs();
}
try {
file.transferTo(dest); // Save a file
return "true";
} catch (Exception e) {
e.printStackTrace();
return "false";
}
}
}
There are some problems with this
The path is wrong
dest is a relative path pointing to upload/doc20170816162034_001. jpg
When the file. transferTo method is called, it is judged that if it is a relative path, the temp directory is used as the parent directory
Therefore, the actual save location is C:\ Users\ xxxx\ AppData\ Local\ Temp\ tomcat.3728730303845252255.8080\ work\ Tomcat\ localhost\ ROOT\ upload\ doc20170816162034_001.jpg
So it is changed to:
@Controller
@RequestMapping("/file")
public class UploadFileController {
@Value("${file.upload.path}")
private String path = "upload/";
@RequestMapping(value = "fileUpload", method = RequestMethod.POST)
@ResponseBody
public 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); // Save a file
return "true";
} catch (Exception e) {
e.printStackTrace();
return "false";
}
}
}