环境:
表单,enctype 和 input 的type=file 即可,例子使用单文件上传
1 2 3 4 5 |
< form enctype = "multipart/form-data" method = "POST"
action = "/file/fileUpload" >
图片< input type = "file" name = "file" />
< input type = "submit" value = "上传" />
</ form >
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
@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); // 保存文件
return "true" ;
} catch (Exception e) {
e.printStackTrace();
return "false" ;
}
}
}
|
运行在保存文件 file.transferTo(dest) 报错
dest 是相对路径,指向 upload/doc20170816162034_001.jpg
file.transferTo 方法调用时,判断如果是相对路径,则使用temp目录,为父目录
因此,实际保存位置为 C:\Users\xxxx\AppData\Local\Temp\tomcat.372873030384525225.8080\work\Tomcat\localhost\ROOT\upload\doc20170816162034_001.jpg
一则,位置不对,二则没有父目录存在,因此产生上述错误。
transferTo 传入参数 定义为绝对路径
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
@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); // 保存文件
return "true" ;
} catch (Exception e) {
e.printStackTrace();
return "false" ;
}
}
}
|
另外也可以 file.getBytes() 获得字节数组,OutputStream.write(byte[] bytes)自己写到输出流中。
application.properties 中增加配置项
1 |
spring.servlet.multipart.location= # Intermediate location of uploaded files.
|
1、增加一个自定义的ResourceHandler把目录公布出去
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
// 写一个Java Config
@Configuration
public class webMvcConfig implements org.springframework.web.servlet.config.annotation.WebMvcConfigurer{
// 定义在application.properties
@Value ( "${file.upload.path}" )
private String path = "upload/" ;
public void addResourceHandlers(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
2、在Controller中增加一个RequestMapping,把文件输出到输出流中
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
@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){
// 通常上传的文件会有一个数据表来存储,这里返回的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( new FileInputStream(source), response.getOutputStream());
} catch (Exception e) {
e.printStackTrace();
}
return null ;
}
}
|
今天使用transferTo这个方法进行上传文件的使用发现了一些路径的一些问题,查找了一下记录问题所在
前端上传网页,使用的是单文件上传的方式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
<!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" >
文件:< input type = "file" name = "head_img" >
姓名:< input type = "text" name = "name" >
< input type = "submit" value = "上传" >
</ form >
</ body >
</ html >
|
后台网页
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
@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); // 保存文件
return "true" ;
} catch (Exception e) {
e.printStackTrace();
return "false" ;
}
}
}
|
这个确实存在一些问题
路径是不对的
dest 是相对路径,指向 upload/doc20170816162034_001.jpg
file.transferTo 方法调用时,判断如果是相对路径,则使用temp目录,为父目录
因此,实际保存位置为 C:\Users\xxxx\AppData\Local\Temp\tomcat.372873030384525225.8080\work\Tomcat\localhost\ROOT\upload\doc20170816162034_001.jpg
所以改为:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
@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); // 保存文件
return "true" ;
} catch (Exception e) {
e.printStackTrace();
return "false" ;
}
}
}
|