springboot 下载 Excel 文件的 Controller 层案例

时间:2024-03-07 09:31:09

环境 pom.xml 中 springboot版本:

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.15</version>
        
    </parent>

Excel 文件依赖:


<!-- POI -->
		<dependency>
			<groupId>org.apache.poi</groupId>
			<artifactId>poi</artifactId>
			<version>4.1.2</version>
		</dependency>
		<dependency>
			<groupId>org.apache.poi</groupId>
			<artifactId>poi-ooxml</artifactId>
			<version>4.1.2</version>
		</dependency>
		<dependency>
			<groupId>org.apache.poi</groupId>
			<artifactId>poi-ooxml-schemas</artifactId>
			<version>4.1.2</version>
		</dependency>
		<dependency>
			<groupId>org.apache.poi</groupId>
			<artifactId>ooxml-schemas</artifactId>
			<version>1.1</version>
		</dependency>

demo1

    // 下载 Excel
    @GetMapping(value = "/downloadData")
    public ResponseEntity<byte[]> downloadData2(
            @RequestParam("id") String id) throws IOException {

        log.info("---------------downloadData start-------------");

        String rootDirectory = request.getServletContext().getRealPath("/");
        log.info("rootDirectory:"+rootDirectory);

        // 临时放置文件目录
        Path p = Paths.get(rootDirectory, "temp");

        if (!p.toFile().exists()) {
            p.toFile().mkdirs();
        }
        log.info("---------------downloadData start 2 Render.... -------------");

        // 写 业务逻辑,生成 Excel File
        File file = null; 
        

        log.info("###------------the excel file address:"+file.getAbsolutePath());

        // 下载成功返回二进制流
        return getResponseEntity(file,null,false);

    }


    private static ResponseEntity<byte[]> getResponseEntity(File file,String userAgent,boolean inline) throws IOException {

        ResponseEntity.BodyBuilder bodyBuilder = ResponseEntity.ok();
        bodyBuilder.contentLength(file.length());
        // 二进制数据流
//        bodyBuilder.contentType(MediaType.APPLICATION_OCTET_STREAM);

        // 文件名编码

        String encodeFileName = URLEncoder.encode(file.getName(), "UTF-8");
        // IE
        if (userAgent!=null&&userAgent.indexOf("MSIE") > 0) {
            bodyBuilder.header("Content-Disposition", "attachment;filename=" + encodeFileName);
        } else { // 其他浏览器

            if (inline) {// 在浏览器中直接打开

                URL url = new URL("file:///" + file);
                bodyBuilder.header("Content-Type", url.openConnection().getContentType());
                bodyBuilder.header("Content-Disposition", "inline;filename*=" + encodeFileName);
            } else {
                // 直接下载

                bodyBuilder.header("Content-Disposition", "attachment;filename*=" + encodeFileName);
                bodyBuilder.header("Content-Type","application/vnd.ms-excel;charset=utf8");
            }


        }
        // 下载成功返回二进制流
        return bodyBuilder.body(Files.readAllBytes(file.toPath()));
    }

demo2

    @GetMapping(value = "/download2")
    public void download2(@RequestParam("id") String id,
                              
                                  @RequestParam(required = false, defaultValue = "false") @ApiParam("参数 inline表示是否要在线浏览,true是,false否(默认).") boolean inline,

                                  @RequestHeader("user-agent") @ApiParam("参数userAgent 是为了兼容IE判断,如果使用谷歌,火狐浏览器就可以省略这个参数.") String userAgent,
                                  ServletRequest request,
                                  HttpServletResponse response) throws IOException {

        String rootDirectory = request.getServletContext().getRealPath("/");
//        System.out.println("rootDirectory:"+rootDirectory);

        // 临时放置文件目录
        Path p = Paths.get(rootDirectory, "temp");

        if (!p.toFile().exists()) {
            p.toFile().mkdirs();
        }


        // 根据业务生成 文件
        File file = new File("");

        this.download(response,file,null);

    }

    private void download(HttpServletResponse response, File file, String fileName){
        if(fileName==null){
            fileName = file.getName();
        }

        try(FileInputStream is = new FileInputStream(file);
            OutputStream os = response.getOutputStream()) {
            //通用的mime类型
            response.setContentType("application/octet-stream");
            response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName,"UTF-8"));



                byte[] buf = new byte[1024];
                int len = 0;
                while((len = is.read(buf))!=-1)
                {
                    os.write(buf,0,len);
                }

        }catch (Exception e) {
            throw new RuntimeException(e);
        }
    }