.dat文件写入byte类型数组_SpringBoot文件上传下载篇(九)

1bd89c802a716f9b606664d71514e4fb.gif

点击上方蓝色字体,关注我们

9c102d30754f2df8c5512459788bbff3.png

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

7c317ddba0c698d65fc504f0a888dd82.pngWhy->MultipartFile?

解析源码:

public interface MultipartFile extends InputStreamSource {

}
public class MockMultipartFile extends Object implements MultipartFile implements MultipartFile, Serializable {

}
public class CommonsMultipartFile implements MultipartFile, Serializable {

}
public interface MultipartFile extends InputStreamSource {

}

通过源码可以看出 MultipartFile是一个接口,这个接口的实现类有 CommonsMultipartFile,MockMultipartFileMultipartFile继承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

7c317ddba0c698d65fc504f0a888dd82.png开始搭建

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

 <properties>
    <java.version>1.8java.version>
properties>
<dependencies>
<dependency>
    <groupId>org.springframework.bootgroupId>
    <artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
    <groupId>org.springframework.bootgroupId>
    <artifactId>spring-boot-starter-thymeleafartifactId>
dependency>
<dependency>
    <groupId>org.springframework.bootgroupId>
    <artifactId>spring-boot-devtoolsartifactId>
    <optional>trueoptional>
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限制,如果上传的文件超过设置的值会出现这个错误。

773d3b1e724f79ec7937377555c36f6d.png

这个错误是因为Spring文件上传重置问题,这个异常是捕获不到,需要Tomcat的默认连接器 maxSwallowSize 的参数。

<Connector port="8080" protocol="HTTP/1.1"connectionTimeout="20000"redirectPort="8443"maxSwallowSize="-1" />

并在上传前实现Javascript检查文件大小。

单文件上传

单文件上传html页面

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>

创建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();
    }
}

操作步骤

6ef19d77e8e93b7104136825d77b098e.gif

单文件上传完成啦,接下来就是多文件上传和文件下载。

ae4627a5ddced3ee520b728c1733f90c.png

多文件上传

html页面

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 "上传文件不能为空";
}

操作步骤

a8fcab2dbb83d0d618da59d997e09950.gif

常见问题

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

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

文件下载方法

@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"));
7c317ddba0c698d65fc504f0a888dd82.png总结

下载的html页面我就不复制啦,一个Spring Boot 上传和下载文件的简单 Demo 就完成了,感兴趣的同学可以将示例代码下载下来试试吧。

GitHub:

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

e773dc77eebfa8bed99feae9ac32cf01.png ba44065d0818fba0219e7a264db3a88f.png 061956e7ccf48485fb35509d39eb9282.png ba44065d0818fba0219e7a264db3a88f.png
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值