zoukankan      html  css  js  c++  java
  • Spring Boot (30) 上传文件

    文件上传

      上传文件和下载文件是Java Web中常见的一种操作,文件上传主要是将文件通过IO流传输到服务器的某一个文件夹下。

    导入依赖

      在pom.xml中添加上spring-boot-starter-web和spring-boot-starter-thymeleaf的依赖

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
    </dependencies>

    配置文件

    默认情况下SPring Boot无需做任何配置也能实现文件上传的功能,但有可能因默认配置不符而导致文件上传失败问题,所以了解相关配置信息更有助于我们对问题的定位和修复。

    spring:
      #禁用thymeleaf缓存
      thymeleaf:
        cache: false
      servlet:
        multipart:
          #是否支持批量上传(默认true)
          enabled: true
          #上传文件的临时目录(一般不用修改)
          location:
          max-file-size: 1048576
          #上传请求最大为10M(默认10M)
          max-request-size: 10485760
          #文件大小阀值,当大于这个阀值时将写入到磁盘,否则存在内存中(默认值0 一般不用修改)
          file-size-threshold: 0
          #判断是否要延迟解析文件(相当于懒加载 一般不用修改)
          resolve-lazily: false

    如果只允许1M以下的文件,当超出该范围则会抛出以下错误

    org.apache.tomcat.util.http.fileupload.FileUploadBase$SizeLimitExceededException: 
    the request was rejected because its size (20738021) exceeds the configured maximum (10485760)

    上传页面

    在src/main/resources下新建static,在static中新建一个index.html的模板文件,实现单文件上传、多文件上传、BASE64编码三种上传方式,其中BASE64的方式在对Android/IOS/H5等方面还是不错的

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>文件上传</title>
    </head>
    <body>
    
    
    <h2>单一文件上传示例</h2>
    <div>
        <form method="POST" enctype="multipart/form-data" action="/uploads/upload1">
            <p>
                文件1:<input type="file" name="file"/>
                <input type="submit" value="上传"/>
            </p>
        </form>
    </div>
    
    <hr/>
    <h2>批量文件上传示例</h2>
    
    <div>
        <form method="POST" enctype="multipart/form-data" action="/uploads/upload2">
            <p>
                文件1:<input type="file" name="file"/>
            </p>
            <p>
                文件2:<input type="file" name="file"/>
            </p>
            <p>
                <input type="submit" value="上传"/>
            </p>
        </form>
    </div>
    
    <hr/>
    <h2>Base64文件上传</h2>
    <div>
        <form method="POST" action="/uploads/upload3">
            <p>
                BASE64编码:<textarea name="base64" rows="10" cols="80"></textarea>
                <input type="submit" value="上传"/>
            </p>
        </form>
    </div>
    
    </body>
    </html>

    控制层

      创建一个FileUploadController,其中@GetMapping的方式用来跳转index.html页面,而@PostMapping相关方法则是对应的单文件上传、多文件上传、BASE64编码三种方式

    @Request("file")此处的file对应的就是html中的name="file"的input标签,而将文件真正写入的还是借助的commons-io中的FileUtils.copyInputStreamToFile(inputStream,file)

    package com.spring.boot.controller;
    
    import org.springframework.stereotype.Controller;
    import org.springframework.util.Base64Utils;
    import org.springframework.util.FileCopyUtils;
    import org.springframework.web.bind.annotation.PostMapping;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestParam;
    import org.springframework.web.bind.annotation.ResponseBody;
    import org.springframework.web.multipart.MultipartFile;
    
    import javax.servlet.http.HttpServletRequest;
    import java.io.File;
    import java.io.IOException;
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    
    @Controller
    @RequestMapping("/uploads")
    public class FileUploadController {
    
        @PostMapping("/upload1")
        @ResponseBody
        public Map<String,String> upload1(@RequestParam("file")MultipartFile imgFile,HttpServletRequest request) throws IOException {
            // 获取文件名
            String fileName = imgFile.getOriginalFilename();
            // 获取图片后缀
            String extName = fileName.substring(fileName.lastIndexOf("."));
            if(extName.equals(".jpg")){
                // 自定义的文件名称
                String trueFileName=String.valueOf(System.currentTimeMillis())+fileName;
                // 设置存放图片文件的路径
                String path="/Users/baidawei/Downloads/imgUpload/" +trueFileName;
                // 开始上传
                imgFile.transferTo(new File(path));
            }
    
            Map<String, String> result = new HashMap<>(16);
            result.put("contentType", imgFile.getContentType());
            result.put("fileName", imgFile.getOriginalFilename());
            result.put("fileSize", imgFile.getSize() + "");
            return result;
        }
    
        @PostMapping("/upload2")
        @ResponseBody
        public List<Map<String,String>> upload2(@RequestParam("file") MultipartFile [] files) throws IOException {
            if(files ==null || files.length == 0){
                return null;
            }
    
            List<Map<String,String>> results = new ArrayList<>();
    
            for(MultipartFile file : files){
                String path="/Users/baidawei/Downloads/imgUpload/" + file.getOriginalFilename();
                file.transferTo(new File(path));
    
                Map<String, String> map = new HashMap<>(16);
                map.put("contentType", file.getContentType());
                map.put("fileName", file.getOriginalFilename());
                map.put("fileSize", file.getSize() + "");
                results.add(map);
            }
            return results;
        }
    
        @PostMapping("/upload3")
        @ResponseBody
        public void upload3(String base64) throws IOException {
            // TODO BASE64 方式的 格式和名字需要自己控制(如 png 图片编码后前缀就会是 data:image/png;base64,)
            final File tempFile = new File("/Users/baidawei/Downloads/imgUpload/test.jpg");
            // TODO 防止有的传了 data:image/png;base64, 有的没传的情况
            String[] d = base64.split("base64,");
            final byte[] bytes = Base64Utils.decodeFromString(d.length > 1 ? d[1] : d[0]);
            FileCopyUtils.copy(bytes,tempFile);
        }
    
    }

    启动项目进行测试:

    http://localhost:8088/

    上传单个返回:

    {"fileName":"sunwukong.jpg","fileSize":"199556","contentType":"image/jpeg"}

    上传多个图片 返回:

    [{"fileName":"狮子头.jpg","fileSize":"187554","contentType":"image/jpeg"},{"fileName":"mh1.jpg","fileSize":"260842","contentType":"image/jpeg"}]

    Base64编码转换地址:http://base64.xpcha.com/pic.html

    需要先把图片转换为base64编码后 再上传

  • 相关阅读:
    进程与线程的区别
    信号列表详解
    同步与互斥
    互斥锁
    读写锁
    Redis QPS测试
    从分布式锁来看redis和zookpeer!
    JVM虚拟机调参
    log4j.properties配置详解与实例
    生产者消费者(消费者要消费完才能退出)
  • 原文地址:https://www.cnblogs.com/baidawei/p/9186775.html
Copyright © 2011-2022 走看看