解决MultipartFile.transferTo(dest) 报FileNotFoundExcep的问题


Posted in Java/Android onJuly 01, 2021

Spring Upload file 报错FileNotFoundException

环境:

  • Springboot 2.0.4
  • JDK8
  • 内嵌 Apache Tomcat/8.5.32

表单,enctype 和 input 的type=file 即可,例子使用单文件上传

<form enctype="multipart/form-data" method="POST"
 action="/file/fileUpload">
 图片<input type="file" name="file" />
 <input type="submit" value="上传" />
</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); // 保存文件
			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 传入参数 定义为绝对路径

@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 中增加配置项

spring.servlet.multipart.location= # Intermediate location of uploaded files.

关于上传文件的访问

1、增加一个自定义的ResourceHandler把目录公布出去

// 写一个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,把文件输出到输出流中

@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;
	}
}

MultipartFile.transferTo(dest) 报找不到文件

今天使用transferTo这个方法进行上传文件的使用发现了一些路径的一些问题,查找了一下记录问题所在

前端上传网页,使用的是单文件上传的方式

<!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>

后台网页

@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

所以改为:

@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";
        }
    }
}

以上为个人经验,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Java/Android 相关文章推荐
java Nio使用NioSocket客户端与服务端交互实现方式
Jun 15 Java/Android
eclipse创建项目没有dynamic web的解决方法
Jun 24 Java/Android
SpringBoot集成Druid连接池连接MySQL8.0.11
Jul 02 Java/Android
gateway网关接口请求的校验方式
Jul 15 Java/Android
深入解读Java三大集合之map list set的用法
Nov 11 Java/Android
SpringDataJPA在Entity中常用的注解介绍
Dec 06 Java/Android
Netty分布式客户端接入流程初始化源码分析
Mar 25 Java/Android
Spring Data JPA框架的核心概念和Repository接口
Apr 28 Java/Android
Java中Dijkstra(迪杰斯特拉)算法
May 20 Java/Android
Android开发手册Chip监听及ChipGroup监听
Jun 10 Java/Android
前端与RabbitMQ实时消息推送未读消息小红点实现示例
Jul 23 Java/Android
AndroidStudio图片压缩工具ImgCompressPlugin使用实例
Aug 05 Java/Android
Java中多线程下载图片并压缩能提高效率吗
分析ZooKeeper分布式锁的实现
Java并发编程必备之Future机制
详解Spring Boot使用系统参数表提升系统的灵活性
Jun 30 #Java/Android
浅谈resultMap的用法及关联结果集映射
Spring中bean的生命周期之getSingleton方法
每日六道java新手入门面试题,通往自由的道路
Jun 30 #Java/Android
You might like
php smarty函数扩展
2010/03/15 PHP
基于PHP选项与信息函数的使用详解
2013/05/10 PHP
PHP登陆后跳转到登陆前页面实现思路及代码
2014/01/17 PHP
PHP批量去除BOM头内容信息代码
2016/03/11 PHP
文本框input聚焦失焦样式实现代码
2012/10/12 Javascript
javascript使用isNaN()函数判断变量是否为数字
2013/09/21 Javascript
原生JavaScript实现合并多个数组示例
2014/09/21 Javascript
JS取得绝对路径的实现代码
2015/01/16 Javascript
深入理解JavaScript中的对象
2015/06/04 Javascript
JavaScript中判断两个字符串是否相等的方法
2015/07/07 Javascript
解决js函数闭包内存泄露问题的办法
2016/01/25 Javascript
jQuery实现为LI列表前3行设置样式的方法【2种方法】
2016/09/04 Javascript
Bootstrap导航条鼠标悬停下拉菜单
2017/01/04 Javascript
Vue头像处理方案小结
2018/07/26 Javascript
深入浅出 Vue 系列 -- 数据劫持实现原理
2019/04/23 Javascript
JavaScript基于面向对象实现的无缝滚动轮播示例
2020/01/17 Javascript
JavaScript实现缓动动画
2020/11/25 Javascript
[42:11]TNC vs Pain 2018国际邀请赛小组赛BO2 第二场 8.17
2018/08/20 DOTA
python实现在字符串中查找子字符串的方法
2015/07/11 Python
Python求两个圆的交点坐标或三个圆的交点坐标方法
2018/11/07 Python
Python神奇的内置函数locals的实例讲解
2019/02/22 Python
python打开windows应用程序的实例
2019/06/28 Python
python生成器/yield协程/gevent写简单的图片下载器功能示例
2019/10/28 Python
Pandas时间序列:重采样及频率转换方式
2019/12/26 Python
使用TensorFlow对图像进行随机旋转的实现示例
2020/01/20 Python
美国特价机票专家:Airfarewatchdog
2018/01/24 全球购物
中海讯通笔试题
2015/09/15 面试题
介绍一下Linux中的链接
2016/05/28 面试题
小学网上祭英烈活动总结
2014/07/05 职场文书
党的群众路线教育实践活动对照检查材料(教师)
2014/09/24 职场文书
高中校园广播稿3篇
2014/09/29 职场文书
优秀党务工作者先进事迹材料
2014/12/25 职场文书
幼师求职自荐信
2015/03/26 职场文书
2015年新农村建设工作总结
2015/05/22 职场文书
高效课堂教学反思
2016/02/24 职场文书
Win11 引入 Windows 365 云操作系统,适应疫情期间混合办公模式:启动时直接登录、模
2022/04/06 数码科技