Java如何向Word模板中插入Base64圖片和數(shù)據(jù)信息
需求
在服務端提前準備好Word模板文件,并在用戶請求接口時服務端動態(tài)獲取圖片。
數(shù)據(jù)等信息插入到模板當中,然后返回包含數(shù)據(jù)信息的Word文件流。
一、準備模板文件
在需要插入圖片的地方使用:{{@參數(shù)名}},文本信息使用:{{參數(shù)名}},進行占位,占位格式將會被保留,經(jīng)過處理后格式不變
將準備好的模板文件放在resources目錄下
二、引入Poi-tl、Apache POI依賴
poi-tl(poi template language)是Word模板引擎,基于Apache POI,提供更友好的API,使用起來更加簡單
版本對應關系參考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)建實體類(用于保存向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; }
四、實現(xiàn)Service接口
public interface DownloadService { void download(HttpServletResponse response, DownloadDTO downloadDTO) throws IOException; }
@Service @Slf4j public class DownloadServiceImpl implements DownloadService { @Resource //遠程調(diào)用服務 private FeignService feignService; @Override public void download(HttpServletResponse response, DownloadDTO downloadDTO) throws IOException {BufferedImage、字節(jié)數(shù)組),Base64可以轉(zhuǎn)字節(jié)數(shù)組后使用 //通過調(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á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"); //設置響應信息 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 { //關閉資源 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層實現(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é)
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關文章
PageHelper插件實現(xiàn)一對多查詢時的分頁問題
這篇文章主要介紹了PageHelper插件實現(xiàn)一對多查詢時的分頁問題,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2019-04-04mybatis初始化SqlSessionFactory失敗的幾個原因分析
這篇文章主要介紹了mybatis初始化SqlSessionFactory失敗的幾個原因分析,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-12-12Spring中配置和讀取多個Properties文件的方式方法
本篇文章主要介紹了Spring中配置和讀取多個Properties文件的方式方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下。2017-04-04JAVA8 stream中三個參數(shù)的reduce方法對List進行分組統(tǒng)計操作
這篇文章主要介紹了JAVA8 stream中三個參數(shù)的reduce方法對List進行分組統(tǒng)計操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-08-08大廠禁止SpringBoot在項目使用Tomcat容器原理解析
這篇文章主要為大家介紹了大廠禁止SpringBoot在項目使用Tomcat原理解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-07-07