文件上传transferTo一行代码的bug
本次的项目环境为 Running with Spring Boot v1.5.10.RELEASE, Spring v4.3.14.RELEASE, 服务器环境为CentOS7.0.
transferTo
我们在上传文件的时候会用到transferTo 这个方法,
transferTo 是 package org.springframework.web.multipart;帮我们已经封装好,所以我们上传文件的时候是很方便的,只需要一行代码。
Spring 大哥真的是强大。
今天我们上传的时候老是报错,错误提示
java.io.IOException: java.io.FileNotFoundException: /opt/xxxxxxx/xxx.png (Is a directory)

蹩脚的英文好好的翻译一下,xxx.png 是一个目录。
对的,看到这里大家大概就明吧了。
String path = FILE_PATH + PATH_NAME + File.separator + dirName;
String fileName = file.getOriginalFilename();
======>注意这里等下要讲的
File targetFile = new File(path , fileName);
if (!targetFile.exists()) {
targetFile.mkdirs();
}
boolean upState = false;
try {
file.transferTo(targetFile);
upState = true;
} catch (IOException e) {
log.error("file transferTo e", e);
e.printStackTrace();
}
分析下
其实这个这里上传文件只是一个方法,用到了 Spring自己封装的MultipartFile类,上传只是用到了transferTo,参数是文件的路径。
好了,来一步步调试看源码。
- 第一步看transferTo中的源码
public void transferTo(File dest) throws IOException, IllegalStateException {
======>注意这里调用的是part 类中的write 方法,参数是File的路径
this.part.write(dest.getPath());
if (dest.isAbsolute() && !dest.exists()) {
FileCopyUtils.copy(this.part.getInputStream(), new FileOutputStream(dest));
}
}
- 第二步看 ApplicationPart 中的write方法
public void write(String fileName) throws IOException {
File file = new File(fileName);
if (!file.isAbsolute()) {
file = new File(this.location, fileName);
}
try {
this.fileItem.write(file);
} catch (Exception var4) {
throw new IOException(var4);
}
}
大家注意看第二步中的 if (!file.isAbsolute()),是的问题就在这里。
这时候如果!file.isAbsolute()成立,也就是我们没有使用绝对路径,那么file = new File(location,fileName);
这个时候会创建一个新的路径,看下面的代码
public File(File parent, String child) {
if (child == null) {
throw new NullPointerException();
}
if (parent != null) {
if (parent.path.equals("")) {
this.path = fs.resolve(fs.getDefaultParent(),
fs.normalize(child));
} else {
this.path = fs.resolve(parent.path,
fs.normalize(child));
}
} else {
this.path = fs.normalize(child);
}
this.prefixLength = fs.prefixLength(this.path);
}
看到这里应该了解了/opt/xxxxxxx/xxx.png ,这个图片被当成文件夹了,在这里创建了一个文件夹,而不是图片。
解决方法
- 代码注入,修改源码中的location
@Bean
MultipartConfigElement multipartConfigElement() {
MultipartConfigFactory factory = new MultipartConfigFactory();
factory.setLocation(你的上传路径path);
return factory.createMultipartConfig();
}
- 文件上传时候创建文件
String path = FILE_PATH + PATH_NAME + File.separator + dirName;
String fileName = file.getOriginalFilename();
======> 注意要先创建图片的目录mkdirs
File sourceFile = new File(path);
if (!sourceFile.exists()) {
sourceFile.mkdirs();
}
File targetFile = new File(path + File.separator + fileName);
boolean upState = false;
try {
file.transferTo(targetFile);
upState = true;
} catch (IOException e) {
log.error("file transferTo e", e);
e.printStackTrace();
}
结论
这里其实就是 new File(path + File.separator + fileName)的问题,因为Spring的源码中不会根据你给的路径自动创建图片的上一层路径。
写这个就是要说明,遇到问题的时候要多读源码,一步步的调试。
当你一步步接近真相的时候,你会感觉到很有成就感,就像爬过一座山头一样。
多读源码 ,不要只是拷贝,很多场景拷贝的时候细节问题不一样的。
文件上传transferTo一行代码的bug的更多相关文章
- BootStrap fileinput.js文件上传组件实例代码
1.首先我们下载好fileinput插件引入插件 ? 1 2 3 <span style="font-size:14px;"><link type="t ...
- java常见3种文件上传速度对比和文件上传方法详细代码
在java里面文件上传的方式很多,最简单的依然是FileInputStream.FileOutputStream了,在这里我列举3种常见的文件上传方法代码,并比较他们的上传速度(由于代码是在本地测试, ...
- JAVA中使用FTPClient实现文件上传下载实例代码
一.上传文件 原理就不介绍了,大家直接看代码吧 ? 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 ...
- ASP.NET - 多文件上传,纯代码,不使用插件
解决方案: 前段代码: <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Mu ...
- 95)PHP,文件上传知识和代码
首先是知识总结: 上传: 从浏览器端传输的到服务器端. 请求时: 数据从浏览器端传输到服务器端. 可见: 上传,发生在浏览器向服务器发出请求过程中. 文件,对于浏览器来讲,就是表单中的一个特殊类型的数 ...
- 全网最简单的大文件上传与下载代码实现(React+Go)
前言 前段时间我需要实现大文件上传的需求,在网上查找了很多资料,并且也发现已经有很多优秀的博客讲了大文件上传下载这个功能. 我的项目是个比较简单的项目,并没有采用特别复杂的实现方式,所以我这篇文章的目 ...
- HDwiki文件上传导致远程代码执行漏洞
漏洞版本: HDwiki(2011) 漏洞描述: 互动维客开源系统(HDwiki)作为中国第一家拥有自主知识产权的中文维基(Wiki)系统,由互动在线(北京)科技有限公司于2006 年11月28日正式 ...
- SFTP 文件上传下载引用代码
http://sha1064616837.iteye.com/blog/2036996 http://www.cnblogs.com/itmanxgl/p/fe5d33512609fe540eb08a ...
- ajaxfileupload多文件上传 - 修复只支持单个文件上传的bug
搜索: jquery ajaxFileUpload AjaxFileUpload同时上传多个文件 原生的AjaxFileUpload插件是不支持多文件上传的,通过修改AjaxFileUpload少量代 ...
随机推荐
- win7+centos6.5安装双系统
前言:之前在琢磨怎么安装双系统 倒腾了两天终于给装上了 使用软件 镜像:CentOS-6.5-x86_64-bin-DVD1.iso 开机引导软件 easybcd2.2 u盘制作软件 USBWrite ...
- Spring返回jsp页面
1.SpringMVC返回的jsp,需要配置相应的viewResolvers,如: <property name="viewResolvers"> <list&g ...
- Java web期末项目第一阶段成果发表
摘要 我们做的系统是一个基于Java web与MySQL的食堂订餐系统 班级: 计科二班 小组成员:李鉴宣.袁超 我们的第一阶段主要完成以下三件事: 完成项目的需求分析 完成项目的领域逻辑(domai ...
- TCP/IP 协议栈初识
原文:深入浅出 TCP/IP 协议栈 0. 简介 TCP/IP 协议栈是网络通信中一系列网络协议的综合,是核心骨架.它定义了电子设备接入因特网.以及数据在它们之间的传输方式,是一份标准.TCP/IP ...
- python socketserver 实现 ftp功能
需求: 用户加密认证 允许同时多用户登录 每个用户有自己的家目录 ,且只能访问自己的家目录 对用户进行磁盘配额,每个用户的可用空间不同 允许用户在ftp server上随意切换目录 允许用户查看当前目 ...
- 算法设计与分析-Week12
题目描述 You are given coins of different denominations and a total amount of money amount. Write a func ...
- 14、创建/恢复ETH钱包身份
借助网上的一段描述: 若以银行账户为类比,这 5 个词分别对应内容如下: 地址=银行卡号密码=银行卡密码私钥=银行卡号+银行卡密码助记词=银行卡号+银行卡密码Keystore+密码=银行卡号+银行卡密 ...
- kettle_errot_karafLifecycleListenter
使用kettle 6.1 通过命令行批量执行作业的过程中,发现偶尔有作业执行时间会变慢几分钟,查看日志发现改作业开始就报了一个错 报错之后才会继续下面的作业,虽然不影响最终作业执行结果,但也延误了一些 ...
- 【教程向】配置属于自己的vim
新建Vim配置文件 Linux mkdir -/.vimrc 配置 常用设置 配置 功能 set number 设置行号 set systax on 高亮 colorscheme{主题} 设置颜色主题 ...
- JS逆向某网站登录密码分析
声明: 本文仅供研究学习使用,请勿用于非法用途! 目标网站 aHR0cHM6Ly9hdXRoLmFsaXBheS5jb20vbG9naW4vaW5kZXguaHRt 今日目标网站是某知名支付网站,感觉 ...