SpringBoot集成文件上传&下载

上传文件是互联网中应用的场景之一,最典型的情况就是上传头像。文件上传主要是将文件通过IO流传输到服务器的某一个特定的文件夹下。

什么是MultipartFile?

解析源码:

public interface MultipartFile extends InputStreamSource {
//StandardMultipartHttpServletRequest 中的静态内部类
private static class StandardMultipartFile implements MultipartFile, Serializable {
	
}
public class CommonsMultipartFile implements MultipartFile, Serializable {

}
public interface MultipartFile extends InputStreamSource {

 

通过源码可以看出 MultipartFile是一个接口,这个接口的实现类有 CommonsMultipartFileMockMultipartFile

MultipartFile继承InputStreamSource这个接口。

接口的常用方法

MultipartFile
    --String getName() //返回表单中file文件参数name的名称。
    --String getOriginalFilename() // 文件原名称
    --String getContentType() //返回文件的内容类型。
    --boolean isEmpty() // 返回上传的文件是否为空,即,在多部分表单中没有选择任何文件,或者所选文件没有内容。
    --long getSize() // 以字节为单位返回文件的大小。
    --byte[] getBytes() //将文件的内容作为字节数组返回。
    --InputStream getInputStream() //返回一个InputStream以从中读取文件的内容。
    --void transferTo(File dest) //将收到的文件传输到给定的目标文件。

参考官网地址:

https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/multipart/MultipartFile.html

开始搭建

环境jdk1.8,引入了spring-boot-starter-thymeleaf做页面模板引擎。

<properties>
        <java.version>1.8</java.version>
</properties>
<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>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-devtools</artifactId>
        <optional>true</optional>
    </dependency>
</dependencies>

application.properties配置文件

#thymeleaf
spring.thymeleaf.prefix=classpath:/templates/
spring.thymeleaf.suffix=.html
spring.thymeleaf.mode=LEGACYHTML5
spring.thymeleaf.encoding=UTF-8
spring.thymeleaf.content-type=text/html
# 禁用 thymeleaf 缓存
spring.thymeleaf.cache=false

# 上传文件总的最大值
spring.servlet.multipart.max-request-size=10MB
# 单个文件的最大值
spring.servlet.multipart.max-file-size=10MB
# 是否支持批量上传   (默认值 true)
spring.servlet.multipart.enabled=true
# 上传文件的临时目录 (一般情况下不用特意修改)
spring.servlet.multipart.location=
# 文件大小阈值,当大于这个阈值时将写入到磁盘,否则存在内存中,(默认值0 一般情况下不用特意修改)
spring.servlet.multipart.file-size-threshold=0
# 判断是否要延迟解析文件(相当于懒加载,一般情况下不用特意修改)
spring.servlet.multipart.resolve-lazily=false

 

注意:

  1、表单method设置为post,并将enctype设置为multipart/form-data。

  2、html中name值要和@RequestParam("file")中的值保持一致。
  3、上传文件大小spring.http.multipart.max-file-size限制,如果上传的文件超过设置的值会出现这个错误。

详细内容参考:Tomcat large file upload connection reset

单文件上传html页面

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>单文件上传</title>
</head>
<body>
<p>单文件上传</p>
<form method="POST" enctype="multipart/form-data" action="/upload" >
    文件:<input type="file" name="file"/>
    <input type="submit"/>
</form>
<hr/>
</body>
</html>

创建FileUploadController中的upload方法 (单文件上传)

@PostMapping("/upload")
    @ResponseBody
    public String upload(@RequestParam("file") MultipartFile file) {
        //判断非空
        if (file.isEmpty()) {
            return "上传的文件不能为空";
        }
        try {
            // 测试MultipartFile接口的各个方法
            logger.info("[文件类型ContentType] - [{}]",file.getContentType());
            logger.info("[文件组件名称Name] - [{}]",file.getName());
            logger.info("[文件原名称OriginalFileName] - [{}]",file.getOriginalFilename());
            logger.info("[文件大小] - [{}]",file.getSize());
            logger.info(this.getClass().getName()+"图片路径:"+path);
            File f = new File(path);
            // 如果不存在该路径就创建
            if (!f.exists()) {
                f.mkdir();
            }
            File dir = new File(path + file.getOriginalFilename());
            // 文件写入
            file.transferTo(dir);
            return "上传单个文件成功";
        } catch (Exception e) {
            e.printStackTrace();
            return "上传单个文件失败";
        }
    }

注:这里除了transferTo方法,也可以用字节流的方式上传文件,但是字节流比较慢,所以还是建议用transferTo
这个是封装的一个用字节流写入文件的方法

  public void writeFile(MultipartFile file) {
        try {
            //获取输出流
            OutputStream os = new FileOutputStream(path + file.getOriginalFilename());
            //获取输入流 CommonsMultipartFile 中可以直接得到文件的流
            InputStream is = file.getInputStream();
            byte[] buffer = new byte[1024];
            //判断输入流中的数据是否已经读完的标识
            int length = 0;
            //循环将输入流读入到缓冲区当中,(len=in.read(buffer))>0就表示in里面还有数据
            while((length = is.read(buffer))!=-1){
                //使用FileOutputStream输出流将缓冲区的数据写入到指定的目录(savePath + "\\" + filename)当中
                os.write(buffer, 0, length);
            }
            os.flush();
            os.close();
            is.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

操作步骤:

                

单文件上传完成啦。

多文件上传

html页面

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>多文件上传</title>
</head>
<body>

<p>多文件上传</p>
<form method="POST" enctype="multipart/form-data" action="/uploadBatch">
    <p>文件1:<input type="file" name="file"/></p>
    <p>文件2:<input type="file" name="file"/></p>
    <p><input type="submit" value="上传"/></p>
</form>
</body>
</html>

uploadBatch方法


    @PostMapping("/uploadBatch")
    @ResponseBody
    public String uploadBatch(@RequestParam("files") MultipartFile[] files) {
        logger.info("文件名称:"+ files );
        if(files!=null&&files.length>0){
            String filePath = "D:\\datafile\\";
            for (MultipartFile mf : files) {
                // 获取文件名称
                String fileName = mf.getOriginalFilename();
                // 获取文件后缀
                String suffixName = fileName.substring(fileName.lastIndexOf("."));
                // 重新生成文件名
                fileName = UUID.randomUUID()+suffixName;

                if (mf.isEmpty()) {
                    return "文件名称:"+ fileName +"上传失败,原因是文件为空!";
                }
                File dir = new File(filePath + fileName);
                try {
                    // 写入文件
                    mf.transferTo(dir);
                    logger.info("文件名称:"+ fileName +"上传成功");
                } catch (IOException e) {
                    logger.error(e.toString(), e);
                    return "文件名称:"+ fileName +"上传失败";
                }
            }
            return "多文件上传成功";
        }
        return "上传文件不能为空";
    }

操作步骤

                                   

 

常见问题

5.1 The field file exceeds its maximum permitted size of 1048576 bytes.

这个错误是由于springboot默认的文件大小是1MB造成的,当上传文件超过1MB时就会报错。解决这个报错可以在application.properties中设置上传参数,参数项是默认的,我们设置最大上传文件大小不超过10MB,再次上传会成功。

实现文件下载的方法

@Controller
public class FileDownloadController {

    private static final Logger logger = LoggerFactory.getLogger(FileDownloadController.class);

    @RequestMapping("/download")
    public String singleFile() {
        return "/download";
    }


    @GetMapping("/downloadfile")
    @ResponseBody
    public String downloadFile(HttpServletRequest request, HttpServletResponse response) throws UnsupportedEncodingException {
        String fileName = "大话设计模式(带目录完整版).pdf";// 文件名

        if (fileName != null) {
            //设置文件路径
            File file = new File("D:\\datafile\\大话设计模式(带目录完整版).pdf");
            //File file = new File(realPath , fileName);
            if (file.exists()) {
                response.setContentType("multipart/form-data");
                response.setHeader("Content-Disposition", "attachment; fileName="+  fileName +";filename*=utf-8''"+ URLEncoder.encode(fileName,"UTF-8"));
                byte[] buffer = new byte[1024];
                FileInputStream fis = null;
                BufferedInputStream bis = null;
                try {
                    fis = new FileInputStream(file);
                    bis = new BufferedInputStream(fis);
                    OutputStream os = response.getOutputStream();
                    int i = bis.read(buffer);
                    logger.info(""+i);
                    while (i != -1) {
                        os.write(buffer, 0, i);
                        i = bis.read(buffer);
                    }
                    return "下载成功";
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    if (bis != null) {
                        try {
                            bis.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                    if (fis != null) {
                        try {
                            fis.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        }
        return "文件不存在";
    }
}

注意在下载文件时,中文文件名称会出现乱码问题,需要设置一下即可。

    response.setHeader("Content-Disposition", "attachment; fileName="+  fileName +";filename*=utf-8''"+ URLEncoder.encode(fileName,"UTF-8"));

总结

一个 Spring Boot 上传文件的简单 Demo 就完成了,感兴趣的同学可以将示例代码下载下来试试吧。

https://github.com/xiaonongOne/springboot-upload

 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值