Angular/Spring Boot Rest API下载Word文档
发表于:2025-02-06 作者:千家信息网编辑
千家信息网最后更新 2025年02月06日,POI生成Word文档使用POI XWPF生成Word文档,引入POI: org.apache.poi poi-ooxml 4.1.0项目中经常从Word模板生成文档,下面示例演示了
千家信息网最后更新 2025年02月06日Angular/Spring Boot Rest API下载Word文档
POI生成Word文档
使用POI XWPF生成Word文档,引入POI:
org.apache.poi poi-ooxml 4.1.0
项目中经常从Word模板生成文档,下面示例演示了替换文档内容的方法。模版中要替换的内容以${}标识,调用XWPFRun.setText()方法更新文档。
import org.apache.poi.xwpf.usermodel.XWPFDocument;import org.apache.poi.xwpf.usermodel.XWPFParagraph;import org.apache.poi.xwpf.usermodel.XWPFRun;import java.io.ByteArrayOutputStream;import java.io.FileInputStream;import java.io.IOException;import java.util.List;import java.util.Map;public final class XWPFDocumentUtils { private XWPFDocumentUtils() { } public static byte[] replaceDocument(String path, Map fields) throws IOException { try (XWPFDocument doc = new XWPFDocument(new FileInputStream(path))) { for (XWPFParagraph paragraph : doc.getParagraphs()) { if (!paragraph.getText().contains("${")) { continue; } replaceParagraph(paragraph, fields); } try (ByteArrayOutputStream out = new ByteArrayOutputStream()) { doc.write(out); return out.toByteArray(); } } } private static void replaceParagraph(XWPFParagraph paragraph, Map fields) { for (Map.Entry field : fields.entrySet()) { String find = "${" + field.getKey() + "}"; if (!paragraph.getText().contains(find)) { continue; } replaceText(paragraph, find, field.getValue()); } } private static void replaceText(XWPFParagraph paragraph, String key, String value) { List runs = paragraph.getRuns(); for (int i = 0; i < runs.size(); i++) { XWPFRun run = runs.get(i); String text = run.text(); if (text.contains("${") || (text.contains("$") && runs.get(i + 1).text().startsWith("{"))) { StringBuilder builder = new StringBuilder(text); while (!text.contains("}")) { text = runs.get(i + 1).text(); builder.append(text); paragraph.removeRun(i + 1); } text = builder.toString(); run.setText(text.contains(key) ? text.replace(key, value) : text, 0); } } }}
Spring Boot Rest API
Rest API
调用replaceDocument()方法生成word文档,如要在Rest API中定义文件名称,使用ResponseEntity并增加header,否则可以直接返回byte[]。
@GetMapping("/api/doc/{heroName}")public ResponseEntity getDocument(@PathVariable String heroName) { try { Map fields = new HashMap<>(); fields.put("hero_name", heroName); fields.put("create_date", "2019年6月"); byte[] bytes = XWPFDocumentUtil.replaceDocument("template/hero.docx", fields); HttpHeaders headers = new HttpHeaders(); headers.add("Content-Disposition", "attachment;filename=hero.docx"); return ResponseEntity.ok().headers(headers).body(bytes); } catch (Exception e) { throw new XWPFDocumentException(e.getMessage()); }}
CORS
配置CORS的ExposedHeaders,否则前台不能读取"Content-Disposition":
@BeanCorsConfigurationSource corsConfigurationSource() { CorsConfiguration configuration = new CorsConfiguration(); SecurityProperties.Cors cors = config.getCors(); configuration.setAllowedMethods(Arrays.asList("*")); configuration.setAllowedHeaders(Arrays.asList("Accept","Accept-Encoding","Accept-Language","Authorization","Connection","Content-Type","Host","Origin","Referer","User-Agent","X-Requested-With")); configuration.setExposedHeaders(Arrays.asList("Content-Disposition")); UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); source.registerCorsConfiguration("/**", configuration); return source;}
Test
测试使用exchange方法,设置header APPLICATION_OCTET_STREAM:
import org.junit.Test;import org.junit.runner.RunWith;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.boot.test.context.SpringBootTest;import org.springframework.boot.test.web.client.TestRestTemplate;import org.springframework.http.*;import org.springframework.test.context.junit4.SpringRunner;import java.util.Arrays;import static org.assertj.core.api.Assertions.assertThat;@RunWith(SpringRunner.class)@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)public class HeroesApplicationTests { @Autowired private TestRestTemplate restTemplate; @Test public void getDocumentSuccess() { HttpHeaders headers = new HttpHeaders(); headers.setAccept(Arrays.asList(MediaType.APPLICATION_OCTET_STREAM)); HttpEntity entity = new HttpEntity<>(headers); ResponseEntity response = restTemplate.exchange("/api/doc/jason", HttpMethod.GET, entity, byte[].class); assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK); }}
Angular下载文档
可以使用链接直接访问REST URL下载文档,若项目启用了JWT Token验证,则必须使用HttpClient的get方法。
本文使用了FileSaver.js保存文档,开始之前先安装:
npm install --save file-saver
然后在tsconfig.json中添加:
"paths": { "file-saver": [ "node_modules/file-saver/dist/FileSaver.js" ]}
下载方法:
import * as fs from 'file-saver';downloadDocument() { this.httpClient.get('yourUrl', {observe: 'response', responseType: 'blob'}).subscribe(response => { fs.saveAs(response.body, this.getFilename(response.headers)); });}private getFilename(headers: HttpHeaders): string { const disposition = headers.get('Content-Disposition'); if (!disposition || disposition.indexOf('filename=') < 0) { return ''; } return disposition.substr(disposition.indexOf('filename=') + 9);}
或
downloadDocument() { this.httpClient.get('yourUrl', {responseType: 'blob'}).subscribe(data => { fs.saveAs(data, 'yourFilename'); });}
参考文档
Excel File - Download from SpringBoot RestAPI + Apache POI + MySQL
Apache POI Word Tutorial
文档
方法
生成
内容
项目
前台
名称
文件
标识
模板
模版
示例
链接
前先
参考
更新
测试
演示
配置
验证
数据库的安全要保护哪些东西
数据库安全各自的含义是什么
生产安全数据库录入
数据库的安全性及管理
数据库安全策略包含哪些
海淀数据库安全审计系统
建立农村房屋安全信息数据库
易用的数据库客户端支持安全管理
连接数据库失败ssl安全错误
数据库的锁怎样保障安全
线束工艺软件开发
江阴信息软件开发价目表
青岛大嘴网络技术有限公司
行政单位网络安全存在的问题
基于数据库连接池技术
原神国际服服务器崩了吗
国内nntp服务器有哪些
scratch云数据库
网络安全保护1000字
网络技术与应用 教案
数据库事务会对表上锁么
口碑好的存储服务器批发
cs go kz服务器
数据库对事物加发管理
软件开发新心得
我的世界俄国服务器
网络安全教育拒绝沉迷网络
绯石之心服务器爆满
苏州微型软件开发五星服务
有应用数据库技术的有哪些
线束工艺软件开发
无锡盘古网络技术公司怎么样
江阴信息软件开发价目表
网络安全产业园发展路径
崂山区软件开发解决方案
万方数据库使用心得
服务器维护管理规程
抗水波动技术和水量服务器
网络安全名词
华为服务器系统盘raid