内容简介:这时候系统将会出现这是什么原因呢?可以进入而后我们再进入
pom包的配置
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
启动项类修改
/**
* 防止文件大于10M时Tomcat连接重置
*
* @return
*/
@Bean
public TomcatServletWebServerFactory tomcatEmbedded() {
TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory();
tomcat.addConnectorCustomizers((TomcatConnectorCustomizer) connector -> {
if ((connector.getProtocolHandler() instanceof AbstractHttp11Protocol<?>)) {
((AbstractHttp11Protocol<?>) connector.getProtocolHandler()).setMaxSwallowSize(-1);
}
});
return tomcat;
}
配置文件修改
# 禁用 thymeleaf 缓存 spring.thymeleaf.cache=false # 是否支持批量上传 (默认值 true) spring.servlet.multipart.enabled=true # 上传文件的临时目录 (一般情况下不用特意修改) spring.servlet.multipart.location= # 上传文件最大为 1M (默认值 1M 根据自身业务自行控制即可) spring.servlet.multipart.max-file-size=10MB # 上传请求最大为 10M(默认值10M 根据自身业务自行控制即可) spring.servlet.multipart.max-request-size=10MB # 文件大小阈值,当大于这个阈值时将写入到磁盘,否则存在内存中,(默认值0 一般情况下不用特意修改) spring.servlet.multipart.file-size-threshold=0 # 判断是否要延迟解析文件(相当于懒加载,一般情况下不用特意修改) spring.servlet.multipart.resolve-lazily=false file.upload.path: /file/upload
单文件上传
@PostMapping("/upload")
public Map<String, String> upload(@RequestParam MultipartFile file) throws IOException {
//创建本地文件
File localFile = new File(path, file.getOriginalFilename());
//把传上来的文件写到本地文件
file.transferTo(localFile);
//返回localFile文件路径
Map<String, String> path = new HashMap<>();
path.put("path", localFile.getAbsolutePath());
return path;
}
这时候系统将会出现 FileNotFoundException
,日志类似下面这样:
java.io.FileNotFoundException:C:\Users\cheng\AppData\Local\Temp\tomcat.7543349588424487992.9000\work\Tomcat\localhost\ROOT\file\upload\tmp\file\upload\1558332190813.jpg (系统找不到指定的路径。)
这是什么原因呢?可以进入 transferTo
方法
@Override
public void transferTo(File dest) throws IOException, IllegalStateException {
this.part.write(dest.getPath());
if (dest.isAbsolute() && !dest.exists()) {
// Servlet 3.0 Part.write is not guaranteed to support absolute file paths:
// may translate the given path to a relative location within a temp dir
// (e.g. on Jetty whereas Tomcat and Undertow detect absolute paths).
// At least we offloaded the file from memory storage; it'll get deleted
// from the temp dir eventually in any case. And for our user's purposes,
// we can manually copy it to the requested location as a fallback.
FileCopyUtils.copy(this.part.getInputStream(), Files.newOutputStream(dest.toPath()));
}
}
而后我们再进入 write
方法
@Override
public void write(String fileName) throws IOException {
File file = new File(fileName);
if (!file.isAbsolute()) {
file = new File(location, fileName);
}
try {
fileItem.write(file);
} catch (Exception e) {
throw new IOException(e);
}
}
这时候我们看到如果 file.isAbsolute()
成立,也就是我们没有使用绝对路径,那么 file = new File(location,fileName);
会在原来的基础上加上location路径.这就是原因所在,可以通过修改绝对路径解决
- 直接将file.upload.path修改为绝对路径即可
-
在代码中控制
@PostMapping("/upload") public Map<String, String> upload(@RequestParam MultipartFile file) throws IOException { //创建本地文件 String classpath = ResourceUtils.getURL("classpath:").getPath(); File localFile = new File(classpath + path, file.getOriginalFilename()); //把传上来的文件写到本地文件 file.transferTo(localFile); //返回localFile文件路径 Map<String, String> path = new HashMap<>(); path.put("path", localFile.getAbsolutePath()); return path; }通过
ResourceUtils.getURL("classpath:").getPath()获得项目路径,然后加上设置的相对路径。网络上还有一种修改
location值的方式,可以看 这篇博客 但是我个人使用是一直不可以。 -
或者可以不使用transferTo,代码如下
@PostMapping("/singleFileUpload") public String singleFileUpload(@RequestParam("file") MultipartFile file) throws IOException { byte[] bytes = file.getBytes(); Path filePath = Paths.get(path + file.getOriginalFilename()); Files.write(filePath, bytes); return file.getOriginalFilename(); }Paths.get所使用的也是绝对路径,如果您在Windows机器上使用了这种路径(从/开始的路径),那么路径将被解释为相对于当前驱动器,例如/file/upload/1.txt
而您的项目位于D盘。那么这条路径就会对应这条完整的路径:
D:\file\upload\1.txt
为了简便,以下代码均是使用绝对路径。
文件上传控制器编写
多文件上传
@PostMapping("/uploads")
public Map<String, String> uploads(@RequestParam MultipartFile[] files) throws IOException {
StringBuilder sb = new StringBuilder();
Map<String, String> paths = new HashMap<>();
for (MultipartFile file : files) {
//创建本地文件
File localFile = new File(path, file.getOriginalFilename());
//把传上来的文件写到本地文件
file.transferTo(localFile);
sb.append(localFile.getAbsolutePath()).append(",");
paths.put(file.getOriginalFilename(), localFile.getAbsolutePath());
}
//返回localFile文件路径
return paths;
}
多文件上传+表单提交
@PostMapping("/uploadsWithForm")
public Map<String, String> uploadsWithForm(@RequestParam String tmpString, @RequestParam MultipartFile[] files) throws IOException {
StringBuilder sb = new StringBuilder();
Map<String, String> paths = new HashMap<>();
paths.put("tmpString", tmpString);
for (MultipartFile file : files) {
//创建本地文件
File localFile = new File(path, file.getOriginalFilename());
//把传上来的文件写到本地文件
file.transferTo(localFile);
sb.append(localFile.getAbsolutePath()).append(",");
paths.put(file.getOriginalFilename(), localFile.getAbsolutePath());
}
//返回localFile文件路径
return paths;
}
多文件上传+Json数据提交
/**
* 测试多文件上传+json接口
*
* @param files
* @return
*/
@ApiOperation("测试多文件上传接口")
@ApiImplicitParams({
@ApiImplicitParam(name = "jsonMap", value = "json数据", dataType = "Map"),
@ApiImplicitParam(name = "files", value = "文件流对象,接收数组格式", required = true, dataType = "__File"),
})
@PostMapping(value = "/uploadsWithJson")
public Map<String, String> uploadsWithJson(@RequestPart("files") MultipartFile[] files, @RequestPart("jsonMap") Map<String, Object> jsonMap) throws IOException {
StringBuilder sb = new StringBuilder();
Map<String, String> paths = new HashMap<>();
System.out.println(jsonMap);
for (MultipartFile file : files) {
//创建本地文件
File localFile = new File(path, file.getOriginalFilename());
//把传上来的文件写到本地文件
file.transferTo(localFile);
sb.append(localFile.getAbsolutePath()).append(",");
paths.put(file.getOriginalFilename(), localFile.getAbsolutePath());
}
paths.put("jsonMap", JsonUtils.obj2json(jsonMap));
//返回localFile文件路径
return paths;
}
呵呵,不好用对不对。项目抛出了个异常, HttpMediaTypeNotSupportedException
。
WARN o.s.w.s.m.support.DefaultHandlerExceptionResolver - Resolved [org.springframework.web.HttpMediaTypeNotSupportedException: Content type 'application/octet-stream' not supported]
所以我们需要添加个转换器类
@Component
public class MultipartJackson2HttpMessageConverter extends AbstractJackson2HttpMessageConverter {
/**
* Converter for support http request with header Content-Type: multipart/form-data
*/
public MultipartJackson2HttpMessageConverter(ObjectMapper objectMapper) {
super(objectMapper, MediaType.APPLICATION_OCTET_STREAM);
}
@Override
public boolean canWrite(Class<?> clazz, MediaType mediaType) {
return false;
}
@Override
public boolean canWrite(Type type, Class<?> clazz, MediaType mediaType) {
return false;
}
@Override
protected boolean canWrite(MediaType mediaType) {
return false;
}
}
这样就能够识别了
总结
感觉把springboot文件上传所能遇到的坑全踩了个变,心累。
如果需要项目代码,可以去我的 github 中下载;
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
程序员的职业素养
Robert C.Martin / 章显洲、余晟 / 人民邮电出版社 / 2012-9-1 / 49.00元
本书是编程大师Bob 大叔40 余年编程生涯的心得体会, 讲解成为真正专业的程序员需要什么样的态度、原则,需要采取什么样的行动。作者以自己以及身边的同事走过的弯路、犯过的错误为例,意在为后来人引路,助其职业生涯迈上更高台阶。 本书适合所有程序员,也可供所有想成为具备职业素养的职场人士参考。一起来看看 《程序员的职业素养》 这本书的介绍吧!