在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

SpringBoot實(shí)現(xiàn)動(dòng)態(tài)導(dǎo)出word文檔

冬至子 ? 來源:ssw在路上的螞蟻 ? 作者:努力的螞蟻 ? 2023-06-05 17:25 ? 次閱讀

背景

最近有一個(gè)需求是需要?jiǎng)討B(tài)導(dǎo)出合同、訂單等信息,導(dǎo)出一個(gè)word文檔供客戶進(jìn)行下載查看。

需要導(dǎo)出的word文件,主要可以分為兩種類型。

  1. 導(dǎo)出固定內(nèi)容和圖片的word文檔
  2. 導(dǎo)出表格內(nèi)容不固定的word文檔

經(jīng)過對(duì)比工具,我實(shí)踐過兩種實(shí)現(xiàn)方式。第一種是FreeMarker模板來進(jìn)行填充;第二種就是文中介紹的POI-TL。

這里我推薦使用POI-TL

介紹

POI-TL是word模板引擎,基于Apache POI,提供更友好的API。

目前最新的版本是1.12.X,POI對(duì)應(yīng)版本是5.2.2。

這里需要注意的是POI和POI-TL有一個(gè)對(duì)應(yīng)的關(guān)系。

圖片

準(zhǔn)備工作

我使用的POI-TL版本是1.10.0

圖片

< dependency >
            < groupId >com.deepoove< /groupId >
            < artifactId >poi-tl< /artifactId >
            < version >1.10.0< /version >
        < /dependency >
        < 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 >commons-io< /groupId >
            < artifactId >commons-io< /artifactId >
            < version >2.7< /version >
        < /dependency >

快速開始

流程:制作模板->提供數(shù)據(jù)->渲染模板->下載word

注意:需要填充的數(shù)據(jù)需要使用{{}}來表示。

1. 導(dǎo)出固定內(nèi)容和圖片的word文檔

準(zhǔn)備模板

圖片

模板保存為docx格式,存放在resource目錄下

圖片

提供數(shù)據(jù)

private Map< String, Object > assertMap() {
        Map< String, Object > params = new HashMap<  >();
        params.put("name", "努力的螞蟻");
        params.put("age", "18");
        params.put("image", Pictures.ofUrl("http://deepoove.com/images/icecream.png").size(100, 100).create());
        return params;
    }

工具方法

/**
     * 將項(xiàng)目中的模板文件拷貝到根目錄下
     * @return
     */
    private String copyTempFile(String templeFilePath) {
        InputStream inputStream = getClass().getClassLoader().getResourceAsStream(templeFilePath);
        String tempFileName = System.getProperty("user.home") + "/" + "1.docx";
        File tempFile = new File(tempFileName);
        try {
            FileUtils.copyInputStreamToFile(inputStream, tempFile);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return tempFile.getPath();
    }
private void down(HttpServletResponse response, String filePath, String realFileName) {
        String percentEncodedFileName = null;
        try {
            percentEncodedFileName = percentEncode(realFileName);
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }
        StringBuilder contentDispositionValue = new StringBuilder();
        contentDispositionValue.append("attachment; filename=").append(percentEncodedFileName).append(";").append("filename*=").append("utf-8''").append(percentEncodedFileName);

        response.addHeader("Access-Control-Allow-Origin", "*");
        response.addHeader("Access-Control-Expose-Headers", "Content-Disposition,download-filename");
        response.setHeader("Content-disposition", contentDispositionValue.toString());
        response.setHeader("download-filename", percentEncodedFileName);
        try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream(filePath));
             // 輸出流
             BufferedOutputStream bos = new BufferedOutputStream(response.getOutputStream());) {
            byte[] buff = new byte[1024];
            int len = 0;
            while ((len = bis.read(buff)) > 0) {
                bos.write(buff, 0, len);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
/**
     * 百分號(hào)編碼工具方法
     * @param s 需要百分號(hào)編碼的字符串
     * @return 百分號(hào)編碼后的字符串
     */
    public static String percentEncode(String s) throws UnsupportedEncodingException {
        String encode = URLEncoder.encode(s, StandardCharsets.UTF_8.toString());
        return encode.replaceAll("\\\\+", "%20");
    }

編寫接口

@RequestMapping("genera")
    public void genera(HttpServletResponse response) {
        //1.組裝數(shù)據(jù)
        Map< String, Object > params = assertMap();
        //2.獲取根目錄,創(chuàng)建模板文件
        String path = copyTempFile("word/1.docx");
        String fileName = System.currentTimeMillis() + ".docx";
        String tmpPath = "D:\\\" + fileName;
        try {
            //3.將模板文件寫入到根目錄
            //4.編譯模板,渲染數(shù)據(jù)
            XWPFTemplate template = XWPFTemplate.compile(path).render(params);
            //5.寫入到指定目錄位置
            FileOutputStream fos = new FileOutputStream(tmpPath);
            template.write(fos);
            fos.flush();
            fos.close();
            template.close();
            //6.提供前端下載
            down(response, tmpPath, fileName);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //7.刪除臨時(shí)文件
            File file = new File(tmpPath);
            file.delete();
            File copyFile = new File(path);
            copyFile.delete();
        }
    }

對(duì)于圖片的格式,POI-TL也提供了幾種方式來提供支撐。

圖片

測試

效果如下:

圖片

2. 導(dǎo)出表格內(nèi)容不固定的word文檔

表格動(dòng)態(tài)內(nèi)容填充,POI-TL提供了3種方式。

  1. 表格行循環(huán)
  2. 表格列循環(huán)
  3. 動(dòng)態(tài)表格。

第二種和第三種都可以實(shí)現(xiàn)表格填充,但我個(gè)人感覺第一種更方便一點(diǎn),這里我只介紹【表格行循環(huán)】實(shí)現(xiàn)方式。

LoopRowTableRenderPolicy 是一個(gè)特定場景的插件,根據(jù)集合數(shù)據(jù)循環(huán)表格行。

注意:

  1. 模板中有兩個(gè)list,這兩個(gè)list需要置于循環(huán)行的上一行。
  2. 循環(huán)行設(shè)置要循環(huán)的標(biāo)簽和內(nèi)容,注意此時(shí)的標(biāo)簽應(yīng)該使用[]

準(zhǔn)備模板

圖片

提供數(shù)據(jù)

學(xué)生實(shí)體類

public class Student {
    private String name;
    private String age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getAge() {
        return age;
    }

    public void setAge(String age) {
        this.age = age;
    }
}

學(xué)生word類

public class StudentTable {
    private String title;
    private List< Student > studentList;

    private List< Student > studentList1;

    public List< Student > getStudentList1() {
        return studentList1;
    }

    public void setStudentList1(List< Student > studentList1) {
        this.studentList1 = studentList1;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public List< Student > getStudentList() {
        return studentList;
    }

    public void setStudentList(List< Student > studentList) {
        this.studentList = studentList;
    }
}

表格數(shù)據(jù)

private StudentTable assertData() {
        StudentTable table = new StudentTable();
        table.setTitle("我是標(biāo)題");
        List< Student > studentList = new ArrayList<  >();
        Student student = new Student();
        student.setName("張三");
        student.setAge("18");
        studentList.add(student);
        Student student1 = new Student();
        student1.setName("李四");
        student1.setAge("20");
        studentList.add(student1);
        Student student2 = new Student();
        student2.setName("王五");
        student2.setAge("21");
        studentList.add(student2);
        Student student3 = new Student();
        student3.setName("馬六");
        student3.setAge("19");
        studentList.add(student3);
        table.setStudentList(studentList);
        table.setStudentList1(studentList);
        return table;
    }

編寫接口

@RequestMapping("dynamicTable")
    public void dynamicTable(HttpServletResponse response) {
        //1.組裝數(shù)據(jù)
        StudentTable table = assertData();
        //2.獲取根目錄,創(chuàng)建模板文件
        String path = copyTempFile("word/2.docx");
        //3.獲取臨時(shí)文件
        String fileName = System.currentTimeMillis() + ".docx";
        String tmpPath = "D:\\\" + fileName;
        try {
            //4.編譯模板,渲染數(shù)據(jù)
            LoopRowTableRenderPolicy hackLoopTableRenderPolicy = new LoopRowTableRenderPolicy();
            Configure config =
                    Configure.builder().bind("studentList", hackLoopTableRenderPolicy).bind("studentList1", hackLoopTableRenderPolicy).build();
            XWPFTemplate template = XWPFTemplate.compile(path, config).render(table);
            //5.寫入到指定目錄位置
            FileOutputStream fos = new FileOutputStream(tmpPath);
            template.write(fos);
            fos.flush();
            fos.close();
            template.close();
            //6.提供下載
            down(response, tmpPath, fileName);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //7.刪除臨時(shí)文件
            File file = new File(tmpPath);
            file.delete();
            File copyFile = new File(path);
            copyFile.delete();
        }
    }

測試

效果如下:

圖片

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • POI
    POI
    +關(guān)注

    關(guān)注

    0

    文章

    8

    瀏覽量

    7033
  • API接口
    +關(guān)注

    關(guān)注

    1

    文章

    84

    瀏覽量

    10463
  • SpringBoot
    +關(guān)注

    關(guān)注

    0

    文章

    173

    瀏覽量

    184
收藏 人收藏

    評(píng)論

    相關(guān)推薦

    如何實(shí)現(xiàn)圖片轉(zhuǎn)Word文檔

    在職場中,有些工作職員經(jīng)常會(huì)受到一些照片,這是令人頭疼,發(fā)照片很簡單,但是要把照片里的信息轉(zhuǎn)移到Word文檔里面就很麻煩了,現(xiàn)在科技快速發(fā)展,難道你還使用手動(dòng)輸入嗎?要是這樣的話,說明你和世界已經(jīng)
    發(fā)表于 04-19 15:05

    基于SpringBoot mybatis方式的增刪改查實(shí)現(xiàn)

    SpringBoot mybatis方式實(shí)現(xiàn)增刪改查
    發(fā)表于 06-18 16:56

    基于多種技術(shù)的Word設(shè)計(jì)文檔自動(dòng)生成平臺(tái)

    闡述Word設(shè)計(jì)文檔自動(dòng)生成平臺(tái)的框架結(jié)構(gòu),提出了結(jié)合VBA、ADO和ASP等技術(shù)的設(shè)計(jì)思路,并詳細(xì)介紹了文檔自動(dòng)生成平臺(tái)軟件的具體實(shí)現(xiàn),包括建立
    發(fā)表于 05-11 20:20 ?30次下載

    一種基于Word文檔的數(shù)字密寫設(shè)計(jì)與實(shí)現(xiàn)

    提出了一種新的基于 Word 文檔的數(shù)字密寫設(shè)計(jì)與實(shí)現(xiàn)方法,介紹了應(yīng)用程序的實(shí)現(xiàn)方案,給出了系統(tǒng)組成方框圖。實(shí)驗(yàn)結(jié)果表明,算法很好地實(shí)現(xiàn)了文
    發(fā)表于 08-04 09:40 ?20次下載

    《微機(jī)原理及應(yīng)用》課程教程 (word文檔)

     《微機(jī)原理及應(yīng)用》課程教案目    錄 下載WORD文檔前    言 下載WORD文檔第一章 51系列單片機(jī)概述
    發(fā)表于 09-16 11:17 ?202次下載

    一種快速Word編程接口的設(shè)計(jì)與實(shí)現(xiàn)

    本文在分析MS Word文檔存儲(chǔ)格式的基礎(chǔ)上,研究了讀取Word文檔二進(jìn)制數(shù)據(jù)流并將其恢復(fù)成可讀信息的方法,設(shè)計(jì)實(shí)現(xiàn)了一種快速
    發(fā)表于 02-21 15:58 ?23次下載

    一種快速Word編程接口的設(shè)計(jì)與實(shí)現(xiàn)

    本文在分析MS Word文檔存儲(chǔ)格式的基礎(chǔ)上,研究了讀取Word文檔二進(jìn)制數(shù)據(jù)流并將其恢復(fù)成可讀信息的方法,設(shè)計(jì)實(shí)現(xiàn)了一種快速
    發(fā)表于 07-22 17:39 ?16次下載

    如何在Word文檔中嵌入PROTEL原理圖

    如何在Word文檔中嵌入PROTEL原理圖 一、Protel 99文件管理器中導(dǎo)入Word文檔:在Protel 99的Documents窗口,執(zhí)行File/New菜單命令,選擇Doc
    發(fā)表于 04-15 00:18 ?1562次閱讀

    VC上機(jī)指導(dǎo)WORD文檔

    VC上機(jī)指導(dǎo)WORD文檔
    發(fā)表于 03-04 17:48 ?2次下載

    word文檔如何解密

    word文檔 如何解密,Kubernetes pod 啟動(dòng)時(shí)會(huì)拉取用戶指定的鏡像,一旦這個(gè)過程耗時(shí)太久就會(huì)導(dǎo)致 pod 長時(shí)間處于 pending 的狀態(tài),從而無法快速提供服務(wù)。
    的頭像 發(fā)表于 03-14 09:10 ?1718次閱讀

    用于損壞的Microsoft Word文檔的數(shù)據(jù)恢復(fù)軟件

    Recoveryfor Word 旨在從損壞的MicrosoftWord 文檔中進(jìn)行有效的數(shù)據(jù)恢復(fù)。使用Word恢復(fù)可以避免丟失重要信息。如今,MicrosoftWord 文本處理器是創(chuàng)建任何類型
    的頭像 發(fā)表于 08-19 15:27 ?1691次閱讀

    SpringBoot實(shí)現(xiàn)多線程

    SpringBoot實(shí)現(xiàn)多線程
    的頭像 發(fā)表于 01-12 16:59 ?1839次閱讀
    <b class='flag-5'>SpringBoot</b><b class='flag-5'>實(shí)現(xiàn)</b>多線程

    求一種SpringBoot定時(shí)任務(wù)動(dòng)態(tài)管理通用解決方案

    SpringBoot的定時(shí)任務(wù)的加強(qiáng)工具,實(shí)現(xiàn)對(duì)SpringBoot原生的定時(shí)任務(wù)進(jìn)行動(dòng)態(tài)管理,完全兼容原生@Scheduled注解,無需對(duì)原本的定時(shí)任務(wù)進(jìn)行修改
    的頭像 發(fā)表于 02-03 09:49 ?795次閱讀

    如何提取Word文檔表格保存到Excel

    據(jù)提取到Excel表中。例如,提取word文檔中的財(cái)務(wù)數(shù)據(jù)、考勤數(shù)據(jù)等,將數(shù)據(jù)存儲(chǔ)到 Excel表中,本次項(xiàng)目我們專門針對(duì)word文檔中的表格數(shù)據(jù)進(jìn)行解析與提取。
    的頭像 發(fā)表于 02-24 16:00 ?2822次閱讀
    如何提取<b class='flag-5'>Word</b><b class='flag-5'>文檔</b>表格保存到Excel

    SpringBoot實(shí)現(xiàn)動(dòng)態(tài)切換數(shù)據(jù)源

    最近在做業(yè)務(wù)需求時(shí),需要從不同的數(shù)據(jù)庫中獲取數(shù)據(jù)然后寫入到當(dāng)前數(shù)據(jù)庫中,因此涉及到切換數(shù)據(jù)源問題。本來想著使用Mybatis-plus中提供的動(dòng)態(tài)數(shù)據(jù)源SpringBoot的starter:dynamic-datasource-spring-boot-starter來
    的頭像 發(fā)表于 12-08 10:53 ?1036次閱讀
    <b class='flag-5'>SpringBoot</b><b class='flag-5'>實(shí)現(xiàn)</b><b class='flag-5'>動(dòng)態(tài)</b>切換數(shù)據(jù)源
    主站蜘蛛池模板: 色妞视频资源在线观看| 人成电影免费观看在线| 河南毛片| 精品综合久久久久久98| 国产美女主播在线| a欧美在线| 天天曰夜夜操| 欧美福利二区| yyy6080韩国三级理论| 日本在线网站| 日韩一级片免费| 国产在线观看午夜不卡| 欧美另类bbw| 99涩涩| 亚洲国产女人aaa毛片在线| 美女被网站免费看九色视频| 不卡视频一区二区三区| 婷婷五月五| 女人张开腿男人猛桶视频| 国产片无遮挡在线看床戏| 在线免费视频| 97人人做人人爱| 天天干2018| 91久久天天躁狠狠躁夜夜| 亚洲精品二区中文字幕| 亚洲人成网站在线在线| 三级在线看| 国产高清在线视频| 色花堂国产精品首页第一页| 啪啪网站免费| 亚洲午夜综合网| 天天干在线播放| 4438x全国最大色| 男女交性永久免费视频播放| 五月婷婷六月激情| 扒开双腿猛进湿润18p| 午夜黄色大片| 噜噜噜色网| 夜夜福利| tdg58在线观看| 高清视频一区二区三区|