Java如何向Word模板中插入Base64圖片和數(shù)據(jù)信息
需求
在服務(wù)端提前準(zhǔn)備好Word模板文件,并在用戶請(qǐng)求接口時(shí)服務(wù)端動(dòng)態(tài)獲取圖片。
數(shù)據(jù)等信息插入到模板當(dāng)中,然后返回包含數(shù)據(jù)信息的Word文件流。
一、準(zhǔn)備模板文件
在需要插入圖片的地方使用:{{@參數(shù)名}},文本信息使用:{{參數(shù)名}},進(jìn)行占位,占位格式將會(huì)被保留,經(jīng)過(guò)處理后格式不變
將準(zhǔn)備好的模板文件放在resources目錄下
二、引入Poi-tl、Apache POI依賴
poi-tl(poi template language)是Word模板引擎,基于Apache POI,提供更友好的API,使用起來(lái)更加簡(jiǎn)單
版本對(duì)應(yīng)關(guān)系參考Poi-tl官網(wǎng)
<!-- 替換自己使用的版本 --> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi</artifactId> <version>4.1.*</version> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>4.1.*</version> </dependency> <!-- Word模板引擎 --> <dependency> <groupId>com.deepoove</groupId> <artifactId>poi-tl</artifactId> <version>1.7.*</version> </dependency>
三、創(chuàng)建實(shí)體類(用于保存向Word中寫入的數(shù)據(jù))
參數(shù)名必須同Word模板中的參數(shù)名稱保持一致
import com.deepoove.poi.data.PictureRenderData; @Data public class DownloadDate { //圖片使用PictureRenderData類型 private PictureRenderData image; private String name; private String a; private String b; private String c; private String d; private String e; private String f; private String g; private String h; private String i; }
四、實(shí)現(xiàn)Service接口
public interface DownloadService { void download(HttpServletResponse response, DownloadDTO downloadDTO) throws IOException; }
@Service @Slf4j public class DownloadServiceImpl implements DownloadService { @Resource //遠(yuǎn)程調(diào)用服務(wù) private FeignService feignService; @Override public void download(HttpServletResponse response, DownloadDTO downloadDTO) throws IOException {BufferedImage、字節(jié)數(shù)組),Base64可以轉(zhuǎn)字節(jié)數(shù)組后使用 //通過(guò)調(diào)用其它接口獲取待寫入的數(shù)據(jù)信息 WordData wordData = feignService.getData(downloadDTO); /** * 圖片可以是多種格式------------------------ * 圖片路徑:PictureRenderData(int width, int height, String path) * File:PictureRenderData(int width, int height, File picture) * InputStream:PictureRenderData(int width, int height, String format, InputStream input) * BufferedImage:PictureRenderData(int width, int height, String format, BufferedImage image) * 字節(jié)數(shù)組:PictureRenderData(int width, int height, String format, byte[] data) * Base64可以轉(zhuǎn)字節(jié)數(shù)組后使用 */ //以Base64為例,先獲取圖片的Base64編碼(wordData.getImg是原始圖片Base64數(shù)據(jù)) String base64ImageData = wordData.getImg.substring(data.indexOf(",") + 1); //獲取圖片類型 String format = getBase64Type(base64ImageData); // 將base64數(shù)據(jù)轉(zhuǎn)為字節(jié)數(shù)組 byte[] imageBytes = Base64.getDecoder().decode(base64ImageData); // 將字節(jié)數(shù)組包裝成PictureRenderData PictureRenderData pictureRenderData = new PictureRenderData(690,530,format,imageBytes); //待寫入Word的數(shù)據(jù) DownloadDate downloadDate = new DownloadDate(); //圖片信息 downloadDate.setImage(pictureRenderData); //其它信息 downloadDate.setName(wordData.getName()); //... XWPFTemplate template = null; BufferedOutputStream bufferedOutputStream = null; ServletOutputStream outputStream = null; try { /** * 該方法會(huì)導(dǎo)致在部分環(huán)境中資源找不到的情況,不推薦使用 */ //獲得resource路徑+模板路徑 //String path = Objects.requireNonNull(Thread.currentThread().getContextClassLoader().getResource("")).getPath() + "word/template.docx"; // 讀取Word模板 //FileInputStream templateInputStream = new FileInputStream(path); // 模板綁定數(shù)據(jù) //template = XWPFTemplate.compile(templateInputStream).render(imageDownloadDate); // 從資源中加載Word模板 try (InputStream templateInputStream = getClass().getClassLoader().getResourceAsStream("word/template.docx")) { if (templateInputStream != null) { // 模板綁定數(shù)據(jù) template = XWPFTemplate.compile(templateInputStream).render(imageDownloadDate); } else { // 處理模板資源未找到的情況 log.error("Word模板資源未找到"); response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); return; } } //文件名 String encodedFileName = URLEncoder.encode(System.currentTimeMillis()+"", "utf-8"); //設(shè)置響應(yīng)信息 response.setHeader("Content-Disposition", "attachment;filename=" + encodedFileName + ".docx"); response.setContentType("application/vnd.openxmlformats-officedocument.wordprocessingml.document"); response.setCharacterEncoding("utf-8"); outputStream = response.getOutputStream(); bufferedOutputStream = new BufferedOutputStream(outputStream); template.write(bufferedOutputStream); //清空流 bufferedOutputStream.flush(); outputStream.flush(); } catch (Exception e) { log.info(e.getMessage()); response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); } finally { //關(guān)閉資源 PoitlIOUtils.closeQuietlyMulti(template, bufferedOutputStream, outputStream); } } //根據(jù)base64編碼獲取圖片格式信息 private String getBase64Type(String base64) { byte[] b = Base64.getDecoder().decode(base64); String type = ".png"; if (0x424D == ((b[0] & 0xff) << 8 | (b[1] & 0xff))) { type = ".bmp"; } else if (0x8950 == ((b[0] & 0xff) << 8 | (b[1] & 0xff))) { type = ".png"; } else if (0xFFD8 == ((b[0] & 0xff) << 8 | (b[1] & 0xff))) { type = ".jpg"; } else if (0x49492A00 == ((b[0] & 0xff) << 24 | (b[1] & 0xff) << 16 | (b[2] & 0xff) << 8 | (b[3] & 0xff))) { type = ".tif"; } return type; } }
五、Controller層實(shí)現(xiàn)
@RestController @RequestMapping("/test") @Api(tags = "獲取商品圖片") public class GetImageController { @Resource DownloadService downloadService; @PostMapping("/download") @ApiOperation(value = "下載Word") void download(HttpServletResponse response,@RequestBody DownloadDTO downloadDTO) throws IOException { //鑒權(quán)或其它處理 //.... downloadService.download(response,downloadDTO); } }
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
PageHelper插件實(shí)現(xiàn)一對(duì)多查詢時(shí)的分頁(yè)問(wèn)題
這篇文章主要介紹了PageHelper插件實(shí)現(xiàn)一對(duì)多查詢時(shí)的分頁(yè)問(wèn)題,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-04-04圖文精講java常見(jiàn)分布式事務(wù)理論與解決方案
對(duì)于分布式系統(tǒng),最簡(jiǎn)單的理解就是一堆機(jī)器對(duì)外提供服務(wù),相比單體服務(wù),它可以承受更高的負(fù)載,但是分布式系統(tǒng)也帶了一系列問(wèn)題,今天帶大家搞懂和分布式相關(guān)的常見(jiàn)理論和解決方案2021-11-11mybatis初始化SqlSessionFactory失敗的幾個(gè)原因分析
這篇文章主要介紹了mybatis初始化SqlSessionFactory失敗的幾個(gè)原因分析,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-12-12詳解關(guān)于SpringBoot的外部化配置使用記錄
這篇文章主要介紹了詳解關(guān)于SpringBoot的外部化配置使用記錄,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-05-05Spring中配置和讀取多個(gè)Properties文件的方式方法
本篇文章主要介紹了Spring中配置和讀取多個(gè)Properties文件的方式方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下。2017-04-04JAVA8 stream中三個(gè)參數(shù)的reduce方法對(duì)List進(jìn)行分組統(tǒng)計(jì)操作
這篇文章主要介紹了JAVA8 stream中三個(gè)參數(shù)的reduce方法對(duì)List進(jìn)行分組統(tǒng)計(jì)操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-08-08大廠禁止SpringBoot在項(xiàng)目使用Tomcat容器原理解析
這篇文章主要為大家介紹了大廠禁止SpringBoot在項(xiàng)目使用Tomcat原理解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-07-07