Angular/Spring Boot Rest API下载Word文档
发表于:2026-11-03 作者:千家信息网编辑
千家信息网最后更新 2026年11月03日,POI生成Word文档使用POI XWPF生成Word文档,引入POI: org.apache.poi poi-ooxml 4.1.0项目中经常从Word模板生成文档,下面示例演示了
千家信息网最后更新 2026年11月03日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安全错误
数据库的锁怎样保障安全
耶加雪菲
花魁咖啡
高科技互联网
厦门中拓互联网络科技有限公司
工业互联网科技新基建
为想互联网科技
银优互联网科技有限公司
郑州华宇互联网科技
齐家互联网科技有限公司
互联网科技有限公司 翻译
卓越科技互联网 招聘
海南科技产业互联网平台
科技赋能互联网健康
江苏南京365互联网科技
中化能源互联网科技招聘
互联网和黑科技的看法
宇信科技在杭州互联网排第几
半导体行业属于互联网高科技类吗
科技信息时代互联网发展
深圳互联网科技园地址
百单网互联网科技有限公司怎么样
互联网科技未来
汽车互联网创新科技园
港股科技和互联网
呼和浩特新华互联网科技学院
深圳互联网科技的发展
启辰互联网科技
广州燕处互联网科技有限公司
10位科技互联网大佬
长沙易易互联网科技有限公司