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 {
//鑒權或其它處理
//....
downloadService.download(response,downloadDTO);
}
}
總結(jié)
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關文章
PageHelper插件實現(xiàn)一對多查詢時的分頁問題
這篇文章主要介紹了PageHelper插件實現(xiàn)一對多查詢時的分頁問題,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2019-04-04
mybatis初始化SqlSessionFactory失敗的幾個原因分析
這篇文章主要介紹了mybatis初始化SqlSessionFactory失敗的幾個原因分析,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-12-12
Spring中配置和讀取多個Properties文件的方式方法
本篇文章主要介紹了Spring中配置和讀取多個Properties文件的方式方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下。2017-04-04
JAVA8 stream中三個參數(shù)的reduce方法對List進行分組統(tǒng)計操作
這篇文章主要介紹了JAVA8 stream中三個參數(shù)的reduce方法對List進行分組統(tǒng)計操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-08-08
大廠禁止SpringBoot在項目使用Tomcat容器原理解析
這篇文章主要為大家介紹了大廠禁止SpringBoot在項目使用Tomcat原理解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-07-07

