springboot2.x文件上传

栏目: Java · 发布时间: 5年前

内容简介:这时候系统将会出现这是什么原因呢?可以进入而后我们再进入

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路径.这就是原因所在,可以通过修改绝对路径解决

  1. 直接将file.upload.path修改为绝对路径即可
  2. 在代码中控制

    @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 值的方式,可以看 这篇博客 但是我个人使用是一直不可以。

  3. 或者可以不使用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 中下载;


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

从零开始做运营

从零开始做运营

张亮 / 中信出版社 / 2015-11-1 / 49.00元

运营是什么?怎样做运营?产品和运营是什么关系?我是否适合从事互联网运营?为什么我做的运营活动收效甚微? 在互联网大热的今天,互联网运营成为一个越来越重要的岗位,事关网站、产品的发展与存亡。很多年轻人带着对互联网的热情投身到这个行业,却发现自己对这个行业所知甚少,对互联网运营更加陌生,甚至有一些有志于从事互联网运营的人,因为对运营缺乏了解而难以确定自己的职业发展方向。本书的出发点就在于此,它将......一起来看看 《从零开始做运营》 这本书的介绍吧!

CSS 压缩/解压工具
CSS 压缩/解压工具

在线压缩/解压 CSS 代码

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具