java WEB导出文件后端,前端代码

本文详细介绍了如何在前端使用location.href替代$.ajax进行请求,以解决导出Excel时无法正常下载的问题。同时,针对火狐浏览器导出文件乱码的情况,提供了通过设置filename参数来解决的方法。此外,还提供了适用于不同浏览器编码设置的代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. 前端请求不能是原来的

$.ajax请求; 

    window.location.href = downScheduleInfoUrl+"?"+参数

 Java后台导出Excel表,没有出现下载提示问题解决
   PS:将访问方式ajax改成  location.href = url就行了。
   https://blog.youkuaiyun.com/a1029573879a/article/details/83419529

 

2. 火狐乱码导出: 设置

https://blog.youkuaiyun.com/bylhjcsmmd/article/details/78284736
|----导出 

在导出的 文件名后边加 filename*=utf-8'zh_cn'"

3. 后台导出代码

	title = java.net.URLDecoder.decode(title, "UTF-8");
		InvoiceInfoBP invoiceInfoBP = new InvoiceInfoBP();
		File file = invoiceInfoBP.downScheduleInfo(invoiceId, tripinfoid, title);
		try {
			Response response = Response.current();
			response.reset();
			response.contentType = "application/msexcel;charset=utf-8";
			response.setHeader("Content-disposition",	"attachment;filename*=utf-8'zh_cn'"+java.net.URLEncoder.encode(java.net.URLDecoder.decode(title.replace("(", "(").replace(")", ")"), "utf-8")+ ".pdf", "UTF-8"));
			if(file!=null){
				FileInputStream input=new FileInputStream(file);
				byte[] bytes=new byte[1024];
				while(input.read(bytes)!=-1){
					response.out.write(bytes);
				}
				if(input!=null){
					input.close();
				}
			}
		} catch (Exception e) {
		
		}

 

 

4. 根据不同浏览器设置不同的编码: 

 

boolean isMSIE = (agent != null && agent.indexOf("MSIE") != -1);// != -1 IE浏览器乱码问题
			if (isMSIE) {
				finafileName = java.net.URLEncoder.encode(fileName, "UTF-8");
			} else {
				finafileName = new String(StringUtil.downloadNameCheck(fileName).getBytes(), "ISO8859_1");
			}

 

<think>我们之前已经讨论了Java后端导出PDF的几种方法,现在用户希望获得前后端配合的完整示例。根据引用[1]和引用[2],用户需要的是从Java后端生成PDF,并通过前端(这里以React为例)触发下载。我们将采用以下方案:后端:使用SpringBoot +iText库生成PDF(直接生成文件流)前端:使用React,通过点击按钮触发下载请求注意:由于引用[2]提到React前端,我们选择React作为前端示例,但原理同样适用于Vue等框架。步骤:1.后端:创建SpringBoot控制器,生成PDF并写入HttpServletResponse2.前端:使用React组件,通过fetch(或axios)请求后端接口,并处理下载详细代码后端(SpringBoot)代码:添加依赖(pom.xml): ```xml<dependency><groupId>com.itextpdf</groupId><artifactId>itextpdf</artifactId><version>5.5.13</version> </dependency>```控制器代码:```javaimportcom.itextpdf.text.Document;import com.itextpdf.text.DocumentException; importcom.itextpdf.text.Paragraph; importcom.itextpdf.text.pdf.PdfWriter; importorg.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RequestMapping; importorg.springframework.web.bind.annotation.RestController;import javax.servlet.http.HttpServletResponse; importjava.io.ByteArrayOutputStream;import java.io.IOException; @RestController@RequestMapping("/api")public classPdfExportController {@GetMapping("/export-pdf")publicvoid exportPdf(HttpServletResponseresponse)throws IOException, DocumentException {//创建文档对象Documentdocument =new Document();ByteArrayOutputStream baos =new ByteArrayOutputStream();//获取PDF写入器PdfWriter.getInstance(document, baos);//打开文档document.open();//添加内容document.add(newParagraph("Hello,PDF Export!"));document.add(newParagraph("这是一段测试内容。"));//关闭文档document.close();//设置响应头response.setContentType("application/pdf");Stringfilename ="exported.pdf";response.setHeader("Content-Disposition","attachment; filename=\""+ filename+ "\"");//将PDF字节数组写入响应输出流response.getOutputStream().write(baos.toByteArray());response.flushBuffer();} }```前端(React)代码:创建一个按钮,点击时调用后端接口下载PDF。 ```jsximportReact from'react'; functionApp() {constdownloadPdf =() =>{//使用fetch调用后端接口fetch('http://localhost:8080/api/export-pdf',{method:'GET',headers:{'Content-Type':'application/pdf',},}).then(response =>{//确保请求成功if(!response.ok){throw newError('Network responsewas notok');}returnresponse.blob();}).then(blob=> {//创建一个临时的URL指向Blob对象consturl =window.URL.createObjectURL(blob);consta =document.createElement('a');a.style.display ='none';a.href =url;//设置下载文件名a.download= 'exported.pdf';document.body.appendChild(a);a.click();//清理window.URL.revokeObjectURL(url);document.body.removeChild(a);}).catch(error=> {console.error('There hasbeen aproblem withyour fetchoperation:',error);});};return(<div><buttononClick={downloadPdf}>导出PDF</button></div>);} exportdefault App; ```注意:前端代码中,我们使用fetch API来请求后端,然后通过创建Blob对象并模拟点击隐藏的<a>标签来实现下载。优化:如果PDF内容复杂(比如包含表格、图片、样式等),建议使用HTML模板转换的方式(如Thymeleaf+Flying Saucer),但这里为了简单直接使用iText生成。解决中文问题:上述代码中直接添加中文可能会出现乱码,需要设置中文字体。下面是如何设置中文字体的示例(需要将字体文件放在资源目录下):```java//在添加内容之前,先设置中文字体BaseFont baseFont =BaseFont.createFont("STSong-Light","UniGB-UCS2-H", BaseFont.EMBEDDED);Font font= newFont(baseFont,12);document.add(new Paragraph("这是一段测试内容。", font)); ```但注意:iText的AGPL协议可能对商业应用有限制,商业项目可考虑购买商业许可或使用其他库(如Apache PDFBox)。相关问题:1.如何在PDF中添加表格?2.如何解决使用iText生成PDF时的中文乱码问题?3.在Spring Boot中如何异步生成PDF以避免阻塞请求线程?4.如何通过HTML模板生成样式丰富的PDF?5.除了iText,还有哪些Java生成PDF的库?</think>### Java后端导出PDF的完整解决方案(含前后端代码) #### 后端实现(Spring Boot) ```java // 添加依赖(pom.xml) <dependency> <groupId>com.itextpdf</groupId> <artifactId>itextpdf</artifactId> <version>5.5.13</version> </dependency> <dependency> <groupId>org.xhtmlrenderer</groupId> <artifactId>flying-saucer-pdf</artifactId> <version>9.1.22</version> </dependency> // PDF生成控制器 @RestController @RequestMapping("/api/pdf") public class PdfController { @Autowired private SpringTemplateEngine templateEngine; // 方法1:直接生成PDF(简单文本) @GetMapping("/simple") public void exportSimplePdf(HttpServletResponse response) throws Exception { // 创建PDF文档 Document document = new Document(); ByteArrayOutputStream baos = new ByteArrayOutputStream(); PdfWriter.getInstance(document, baos); // 添加内容(解决中文乱码) BaseFont baseFont = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.EMBEDDED); Font font = new Font(baseFont, 12); document.open(); document.add(new Paragraph("销售报告", font)); document.add(new Paragraph("日期: " + LocalDate.now(), font)); document.add(new Paragraph("总金额: ¥15,800", font)); document.close(); // 设置响应头 response.setContentType("application/pdf"); response.setHeader("Content-Disposition", "attachment; filename=report.pdf"); response.getOutputStream().write(baos.toByteArray()); } // 方法2:HTML模板转PDF(推荐) @PostMapping("/from-html") public void exportHtmlPdf(@RequestBody PdfRequest request, HttpServletResponse response) throws Exception { // 渲染HTML模板 Context context = new Context(); context.setVariable("title", request.getTitle()); context.setVariable("items", request.getItems()); String html = templateEngine.process("pdf-template", context); // 转换为PDF ITextRenderer renderer = new ITextRenderer(); renderer.setDocumentFromString(html); renderer.layout(); // 输出PDF response.setContentType("application/pdf"); response.setHeader("Content-Disposition", "attachment; filename=" + request.getFileName()); renderer.createPDF(response.getOutputStream()); } } // 请求DTO public class PdfRequest { private String title; private String fileName; private List<Item> items; // getters/setters } // HTML模板(src/main/resources/templates/pdf-template.html) <!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head> <style> body { font-family: SimSun; } table { width: 100%; border-collapse: collapse; } th, td { border: 1px solid #ddd; padding: 8px; } th { background-color: #f2f2f2; } </style> </head> <body> <h1 th:text="${title}">报告标题</h1> <table> <tr> <th>产品名称</th> <th>数量</th> <th>单价</th> <th>总价</th> </tr> <tr th:each="item : ${items}"> <td th:text="${item.name}"></td> <td th:text="${item.quantity}"></td> <td th:text="'¥' + ${item.price}"></td> <td th:text="'¥' + ${item.total}"></td> </tr> </table> </body> </html> ``` #### 前端实现(React) ```jsx import React, { useState } from 'react'; function PdfExporter() { const [loading, setLoading] = useState(false); // 简单PDF下载 const downloadSimplePdf = () => { setLoading(true); fetch('/api/pdf/simple') .then(response => response.blob()) .then(blob => { const url = window.URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = 'simple-report.pdf'; a.click(); setLoading(false); }); }; // 动态数据PDF下载 const downloadDynamicPdf = () => { setLoading(true); const requestData = { title: "2023年销售报告", fileName: "sales-report.pdf", items: [ { name: "笔记本电脑", quantity: 15, price: 6500, total: 97500 }, { name: "智能手机", quantity: 30, price: 3999, total: 119970 } ] }; fetch('/api/pdf/from-html', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(requestData) }) .then(response => response.blob()) .then(blob => { const url = window.URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = requestData.fileName; a.click(); setLoading(false); }); }; return ( <div className="pdf-export"> <button onClick={downloadSimplePdf} disabled={loading}> {loading ? '生成中...' : '下载简单PDF'} </button> <button onClick={downloadDynamicPdf} disabled={loading} style={{ marginLeft: '10px' }}> {loading ? '生成中...' : '下载动态PDF'} </button> </div> ); } ``` #### 关键技术说明 1. **PDF生成方式**: - **直接生成**:适合简单文本内容 - **HTML模板转换**:推荐方案,支持复杂样式和动态数据[^1] - 使用`Flying Saucer`将HTML+CSS转换为PDF 2. **中文支持**: ```java // 必须嵌入中文字体 BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.EMBEDDED); ``` 3. **性能优化**: ```java // 大文件处理 response.setBufferSize(1024 * 1024); // 1MB缓冲区 // 异步生成 @Async public void generatePdfAsync(...) { ... } ``` 4. **前端交互**: - 使用Blob API处理二进制流 - 通过创建隐藏的`<a>`标签触发下载 - 添加加载状态提升用户体验 #### 部署注意事项 1. **字体文件**: - 将中文字体(如simsun.ttf)放在`src/main/resources/fonts`目录 - 在HTML模板中引用: ```css @font-face { font-family: "SimSun"; src: url("./fonts/simsun.ttf"); } ``` 2. **PDF表格**: ```java // 创建表格 PdfPTable table = new PdfPTable(4); table.addCell("产品"); table.addCell("价格"); document.add(table); ``` 3. **分页控制**: ```java writer.setPageEvent(new PdfPageEvent() { @Override public void onEndPage(PdfWriter writer, Document document) { // 添加页脚 ColumnText.showTextAligned(writer.getDirectContent(), Element.ALIGN_CENTER, new Phrase("第"+page+"页"), document.right(), 30, 0); } }); ``` #### 相关问题 1. 如何在PDF中添加水印和页眉页脚? 2. 使用iText生成PDF时如何实现自动分页? 3. 在微服务架构中如何优化PDF生成服务的性能? 4. 除了iText,还有哪些商用友好的Java PDF生成库? 5. 如何将数据库查询结果直接导出为带图表和样式的PDF?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值