SpringBoot结合MultipartFile类实现文件上传与文件下载

前言

  1. 文件上传下载应用场景很多。比如:我们在修改头像的时候,需要上传头像;我们在后台修改商品信息的时候,也需要上传商品图片。作为Java开发者,文件上传与文件下载功能已经是必会的技能。
  2. 这次使用SpringBoot实现单文件上传,多文件上传以及文件下载,重点介绍MultipartFile工具类。

文件上传到哪里合适?

我们在实现文件上传功能的时候,也需要结合实际场景来决定文件的上传位置,一般来说有三种采纳方案:

  1. 将文件上传到工程目录下:在一些文件存储量很小的工程中,有一些上传文件放置在工程本身的目录下,但是随着文件上传的量越来越大,工程本身所在的文件夹容量会越来越大,不仅打包和部署的效率会降低,工程的启动和运行也会变慢,所以一般不会采用这做法。
  2. 将文件上传到工程所在服务器:将文件专门上传到Web应用工程所在容器(如Tomcat)位于的服务器中,单独开辟一个盘符或文件夹用于存储上传的图片,这种做法让上传 文件与工程本身分离,工程的打包和启动效率不受到任何影响。但是如果以后出现了海量图片,Web应用工程所在的服务器的效率会降低,这样也会间接地降低应用的执行效率,所以在上传图片量不大的情况下,可以采用该做法。
  3. 搭建文件服务器:一般大型的互联网项目,都会为自己的文件上传单独架设一个文件服务器(有集群的应用,可能会有多台文件服务器),也有独立处理文件上传、文件访问的服务器。这种方案就是太烧钱。

上面分析了三种方案的特点和优缺点。第一种一般不采取,第二种可能会采取,最常用的就是第三种方案。

MultipartFile工具类

  1. MultipartFile是SpringMVC提供简化上传操作的工具类。
  2. 在不使用框架之前,都是使用原生的HttpServletRequest来接收上传的数据,文件是以二进制流传递到后端的,然后需要我们自己转换为File类,非常麻烦。使用了MultipartFile工具类之后,我们对文件上传的操作就简便许多了。
  3. 以下是MultipartFile工具类全部的接口方法。
方法名 返回值 作用
getContentType() String 在取文件MIME类型
getlnputStream() InputStream 获取文件流
getName() String 获取 form 表单中文件组件的名字
getOriginalFilename() String 获取上传文件件的原名
getSize() long 获取文件的大小,单位为byte
isEmpty() boolean 是否为空
transferTo(File dest) void 将数据保存到一个目标文件中

单文件上传

  1. 文件上传的表单和普通表单有一点不同之处,就是需要添加enctype="multipart/form-data"这个属性,暗指该表单存在文件上传。
    
    <form action="/uploadFile" method="post" enctype="multipart/form-data">
        <p>文件:<input type="file" name="file"/>p>
        <p><input type="submit" value="上传"/>p>
    form>
    
    @RestController
    @Slf4j
    public class FileController {
    	@PostMapping("upload")
    	public String upload(MultipartFile file){
    	    try {
    	        if (file.isEmpty()){
    	            return "文件为空";
    	        }
    	        //获取文件名
    	        String fileName = file.getOriginalFilename();
    	        log.info("上传的文件名:"+fileName);
    	        //获取文件后缀名
    	        String suffixName = fileName.substring(fileName.lastIndexOf("."));
    	        log.info("文件后缀名:"+suffixName);
    	        //设置文件存储路径
    	        String filePath = "f:/upload/";
    	        String path = filePath+fileName;
    	        File dest = new File(path);
    	        //检测是否存在该目录
    	        if (!dest.getParentFile().exists()){
    	            dest.getParentFile().mkdirs();
    	        }
    	        //写入文件
    	        file.transferTo(dest);
    	        return "上传成功!";
    	    } catch (IOException e) {
    	        e.printStackTrace();
    	    }
    	    return "上传失败";
    	}
    }
    

多文件上传

  1. 文件上传的表单和普通表单有一点不同之处,就是需要添加enctype="multipart/form-data"这个属性,暗指该表单存在文件上传。
    
    <form action="batchUpload" method="post" enctype="multipart/form-data">
        <p>文件1:<input type="file" name="file"/>p>
        <p>文件2:<input type="file" name="file"/>p>
        <p><input type="submit" value="批量上传"/>p>
    form>
    
    @RestController
    @Slf4j
    public class FileController {
    	/**
    	*  多文件上传流程
    	*      1.前端上传多个文件
    	*      2.后台使用请求对象(MultipartHttpServletRequest)接收整个请求流
    	*      3.获取MultipartFile集合
    	*      4.定义缓冲字节输出流
    	*      5.遍历MultipartFile集合
    	*      6.获取每一个MultipartFile对象
    	*      7.定义上传路径
    	*      8.判断上传文件是否为空(也就是没有上传)
    	*      9.如果不为空,则通过缓冲字节输出流写入到上传路径
    	*/
    	@PostMapping("batchUpload")
    	public String batchUpload(MultipartHttpServletRequest request){
    	    List<MultipartFile> files = request.getFiles("file");
    	    MultipartFile file = null;
    	    BufferedOutputStream stream = null;
    	    for (int i = 0; i < files.size(); i++) {
    	        file = files.get(i);
    	        String filePath = "f:/upload/";
    	        if (!file.isEmpty()){
    	            try {
    	                byte[] bytes = file.getBytes();
    	                stream = new BufferedOutputStream(new FileOutputStream(new File(filePath+file.getOriginalFilename())));
    	                stream.write(bytes);
    	                stream.close();
    	            } catch (IOException e) {
    	                stream = null;
    	                return "第"+i+"个文件上传失败:"+e.getMessage();
    	            }
    	        }else {
    	            return "第"+i+"个文件上传失败因为文件为空";
    	        }
    	    }
    	    return "上传成功";
    	}
    }
    

文件下载

  1. 下载文件就是程序读取文件流,然后响应到客户端(输出流操作)。
    
    <a href="download">文件下载a>
    
    @RestController
    @Slf4j
    public class FileController {
    	@GetMapping("/download")
    	public String downloadFile(HttpServletRequest request, HttpServletResponse response) {
    	    String fileName = "boss.jpg";// 文件名
    	    if (fileName != null) {
    	        //设置文件路径
    	        File file = new File("f:/upload/boss.jpg");
    	        //File file = new File(realPath , fileName);
    	        if (file.exists()) {
    	            response.setContentType("application/force-download");// 设置强制下载不打开
    	            response.addHeader("Content-Disposition", "attachment;fileName=" + fileName);// 设置文件名
    	            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);
    	                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 "下载失败";
    	}
    }
    

你可能感兴趣的:(SpringBoot)