Commit 8840ebf2 authored by 盖献康's avatar 盖献康

导出PDF-demo

parent 53f70cb0
package com.ruoyi.service; package com.ruoyi.service;
import com.itextpdf.text.Document;
import com.ruoyi.domain.Book; import com.ruoyi.domain.Book;
import com.baomidou.mybatisplus.extension.service.IService; import com.baomidou.mybatisplus.extension.service.IService;
import org.apache.skywalking.apm.toolkit.trace.Tag; import org.apache.skywalking.apm.toolkit.trace.Tag;
import org.apache.skywalking.apm.toolkit.trace.Tags; import org.apache.skywalking.apm.toolkit.trace.Tags;
import org.apache.skywalking.apm.toolkit.trace.Trace; import org.apache.skywalking.apm.toolkit.trace.Trace;
import javax.servlet.http.HttpServletResponse;
import java.io.OutputStream;
import java.util.List; import java.util.List;
/** /**
...@@ -19,4 +22,19 @@ public interface BookService extends IService<Book> { ...@@ -19,4 +22,19 @@ public interface BookService extends IService<Book> {
List<Book> selectBookListException(String name); List<Book> selectBookListException(String name);
/**
* 生成PDF
* @param os
* @return
* @throws Exception
*/
Document generateItextPdfDocument(OutputStream os) throws Exception;
/**
* 以模板生成
* @param response
* @throws Exception
*/
void generateTempPDF(HttpServletResponse response) throws Exception;
} }
package com.ruoyi.service.impl; package com.ruoyi.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.itextpdf.text.*;
import com.itextpdf.text.pdf.*;
import com.itextpdf.text.pdf.codec.Base64;
import com.ruoyi.common.exception.ServiceException; import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.PdfUtils;
import com.ruoyi.domain.Book; import com.ruoyi.domain.Book;
import com.ruoyi.service.BookService; import com.ruoyi.service.BookService;
import com.ruoyi.mapper.BookMapper; import com.ruoyi.mapper.BookMapper;
...@@ -9,9 +13,19 @@ import org.apache.skywalking.apm.toolkit.trace.Tag; ...@@ -9,9 +13,19 @@ import org.apache.skywalking.apm.toolkit.trace.Tag;
import org.apache.skywalking.apm.toolkit.trace.Tags; import org.apache.skywalking.apm.toolkit.trace.Tags;
import org.apache.skywalking.apm.toolkit.trace.Trace; import org.apache.skywalking.apm.toolkit.trace.Trace;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map;
/** /**
* @author wangfei * @author wangfei
...@@ -38,6 +52,178 @@ public class BookServiceImpl extends ServiceImpl<BookMapper, Book> implements Bo ...@@ -38,6 +52,178 @@ public class BookServiceImpl extends ServiceImpl<BookMapper, Book> implements Bo
} }
return null; return null;
} }
@Override
public Document generateItextPdfDocument(OutputStream os) throws Exception {
// document
Document document = new Document(PageSize.A4);
PdfWriter.getInstance(document, os);
// open
document.open();
// add content - pdf meta information
document.addAuthor("pdai");
document.addCreationDate();
document.addTitle("pdai-pdf-itextpdf");
document.addKeywords("pdf-pdai-keyword");
document.addCreator("pdai");
// add content - page content
// Title
document.add(PdfUtils.createTitle("Java 全栈知识体系"));
// Chapter 1
document.add(PdfUtils.createChapterH1("1. 知识准备"));
document.add(PdfUtils.createChapterH2("1.1 什么是POI"));
document.add(PdfUtils.createParagraph("Apache POI 是创建和维护操作各种符合Office Open XML(OOXML)标准和微软的OLE 2复合文档格式(OLE2)的Java API。用它可以使用Java读取和创建,修改MS Excel文件.而且,还可以使用Java读取和创建MS Word和MSPowerPoint文件。更多请参考[官方文档](https://poi.apache.org/index.html)"));
document.add(PdfUtils.createChapterH2("1.2 POI中基础概念"));
document.add(PdfUtils.createParagraph("生成xls和xlsx有什么区别?POI对Excel中的对象的封装对应关系?"));
// Chapter 2
document.add(PdfUtils.createChapterH1("2. 实现案例"));
document.add(PdfUtils.createChapterH2("2.1 用户列表示例"));
document.add(PdfUtils.createParagraph("以导出用户列表为例"));
// 表格
PdfPTable table = new PdfPTable(new float[]{20, 40, 50, 40, 40});
table.setTotalWidth(500);
table.setLockedWidth(true);
table.setHorizontalAlignment(Element.ALIGN_CENTER);
table.getDefaultCell().setBorder(1);
for (int i = 0; i < 5; i++) {
table.addCell(PdfUtils.createCell("1"));
table.addCell(PdfUtils.createCell("2"));
table.addCell(PdfUtils.createCell("3"));
table.addCell(PdfUtils.createCell("4"));
table.addCell(PdfUtils.createCell("5"));
}
document.add(table);
document.add(PdfUtils.createChapterH2("2.2 图片导出示例"));
document.add(PdfUtils.createParagraph("以导出图片为例"));
// 图片
Image image = Image.getInstance("C:/Users/gxk/Pictures/Saved Pictures/nvm.png");
image.setAlignment(Element.ALIGN_CENTER);
// 缩放
image.scalePercent(60);
document.add(image);
// close
document.close();
return document;
}
@Override
public void generateTempPDF(HttpServletResponse response) throws Exception {
PdfReader reader = null;
PdfStamper ps = null;
OutputStream fos = null;
ByteArrayOutputStream bos = null;
Base64.InputStream fin = null;
ServletOutputStream out = null;
try {
// 模板绝对路径--服务器
String fileName = "/template/receipt_template.pdf";
// 读取现有模板内容
reader = new PdfReader(fileName);
// 创建输出流
bos = new ByteArrayOutputStream();
// 实例化PdfStamper准备编辑pdf内容
ps = new PdfStamper(reader, bos);
// 获取表单所有元素
AcroFields fields = ps.getAcroFields();
// 设置具体字体格式的编码, 不设置的话中文可能不会显示
BaseFont bf = BaseFont.createFont("STSongStd-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
fields.addSubstitutionFont(bf);
// 动态添加所需要的数据,key跟模板中对应文本域名称一致
Map<String, String> map = new HashMap<>();
map.put("code", "1234567890fjdksjfdsfdsffdsjfdssssssttttttttttttttt");
map.put("table_image", "C:/Users/gxk/Pictures/Saved Pictures/nvm.png");
// 渲染
fillData(fields, map, ps);
//必须要调用这个,否则文档不会生成的
ps.setFormFlattening(true);
if(ps != null){
ps.close();
}
//生成pdf路径存放的路径
fos = response.getOutputStream();
fos.write(bos.toByteArray());
}catch (Exception e){
e.printStackTrace();
}finally {
if(fos!=null){
fos.flush();
fos.close();
}
if (bos != null){
bos.close();
}
if(reader != null){
reader.close();
}
}
}
/**
* 填充模板中的数据
* @param fields
* @param data 是一个Map<String,String> 主要存储 key 表单模板中的单元格名 value为想要赋的值,遍历
* @param ps
*/
public void fillData(AcroFields fields, Map<String, String> data, PdfStamper ps) {
try {
for (String key : data.keySet()) {
String value = data.get(key);
if (key.contains("image")) {
addImageToPdf(key, fields, ps, value);
continue;
}
// 为字段赋值,注意字段名称是区分大小写的
fields.setField(key, value);
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 添加图片
* @param key 应为模板名
* @param form 动态字段
* @param stamper
* @param filePath 本地图片路径
* @throws DocumentException
* @throws IOException
* @throws IOException
*/
private static void addImageToPdf(String key,AcroFields form, PdfStamper stamper, String filePath) throws DocumentException, IOException, IOException {
// 通过图片域名获取所在页和坐标,左下角为起点
int pageNo = form.getFieldPositions(key).get(0).page;
Rectangle signRect = form.getFieldPositions(key).get(0).position;
float x = signRect.getLeft();
float y = signRect.getBottom();
// 读图片
Image image = Image.getInstance(filePath);
// 获取操作的页面
PdfContentByte under = stamper.getOverContent(pageNo);
// 根据域的大小缩放图片
image.scaleToFit(signRect.getWidth() * 2, signRect.getHeight());
// 添加图片并设置位置(个人通过此设置使得图片垂直水平居中,可参考,具体情况已实际为准)
image.setAbsolutePosition(x, y);
under.addImage(image);
}
} }
......
package com.ruoyi.web; package com.ruoyi.web;
import com.itextpdf.text.Document;
import com.ruoyi.common.annotation.Anonymous;
import com.ruoyi.common.core.controller.BaseController; import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.R; import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.page.TableDataInfo; import com.ruoyi.common.core.page.TableDataInfo;
...@@ -9,6 +11,7 @@ import com.ruoyi.web.request.BookDeleteRequest; ...@@ -9,6 +11,7 @@ import com.ruoyi.web.request.BookDeleteRequest;
import com.ruoyi.web.request.BookListRequest; import com.ruoyi.web.request.BookListRequest;
import io.swagger.annotations.Api; import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.skywalking.apm.toolkit.trace.Tag; import org.apache.skywalking.apm.toolkit.trace.Tag;
import org.apache.skywalking.apm.toolkit.trace.Tags; import org.apache.skywalking.apm.toolkit.trace.Tags;
import org.apache.skywalking.apm.toolkit.trace.Trace; import org.apache.skywalking.apm.toolkit.trace.Trace;
...@@ -16,6 +19,8 @@ import org.springframework.beans.factory.annotation.Autowired; ...@@ -16,6 +19,8 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletResponse;
import java.io.OutputStream;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
...@@ -73,4 +78,17 @@ public class BookController extends BaseController { ...@@ -73,4 +78,17 @@ public class BookController extends BaseController {
return getDataTable(books); return getDataTable(books);
} }
@Anonymous
@ApiOperation("Download")
@GetMapping(value = "/download", produces = "application/json")
public void download(HttpServletResponse response) {
response.setHeader("content-disposition","attachment;fileName="+"ReceiptPrinter.pdf");
try {
// bookService.generateItextPdfDocument(response.getOutputStream());
bookService.generateTempPDF(response);
} catch (Exception e) {
e.printStackTrace();
}
}
} }
...@@ -52,13 +52,13 @@ ...@@ -52,13 +52,13 @@
<groupId>org.apache.commons</groupId> <groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId> <artifactId>commons-lang3</artifactId>
</dependency> </dependency>
<!-- JSON工具类 --> <!-- JSON工具类 -->
<dependency> <dependency>
<groupId>com.fasterxml.jackson.core</groupId> <groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId> <artifactId>jackson-databind</artifactId>
</dependency> </dependency>
<!-- 动态数据源 --> <!-- 动态数据源 -->
<dependency> <dependency>
<groupId>com.baomidou</groupId> <groupId>com.baomidou</groupId>
...@@ -158,6 +158,17 @@ ...@@ -158,6 +158,17 @@
<version>3.0.3</version> <version>3.0.3</version>
</dependency> </dependency>
<!-- PDF -->
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itextpdf</artifactId>
<version>5.5.13.3</version>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itext-asian</artifactId>
<version>5.2.0</version>
</dependency>
</dependencies> </dependencies>
</project> </project>
\ No newline at end of file
package com.ruoyi.common.utils;
import com.itextpdf.text.*;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfPCell;
import java.io.IOException;
/**
* PDF工具类
* @author gxk
*/
public class PdfUtils {
/**
* 标题
* @param content
* @return
* @throws IOException
* @throws DocumentException
*/
public static Paragraph createTitle(String content) throws IOException, DocumentException {
Font font = new Font(getBaseFont(), 24, Font.BOLD);
Paragraph paragraph = new Paragraph(content, font);
paragraph.setAlignment(Element.ALIGN_CENTER);
return paragraph;
}
/**
* H1标题
* @param content
* @return
* @throws IOException
* @throws DocumentException
*/
public static Paragraph createChapterH1(String content) throws IOException, DocumentException {
Font font = new Font(getBaseFont(), 22, Font.BOLD);
Paragraph paragraph = new Paragraph(content, font);
paragraph.setAlignment(Element.ALIGN_LEFT);
return paragraph;
}
/**
* H2标题
* @param content
* @return
* @throws IOException
* @throws DocumentException
*/
public static Paragraph createChapterH2(String content) throws IOException, DocumentException {
Font font = new Font(getBaseFont(), 18, Font.BOLD);
Paragraph paragraph = new Paragraph(content, font);
paragraph.setAlignment(Element.ALIGN_LEFT);
return paragraph;
}
/**
* 段
* @param content
* @return
* @throws IOException
* @throws DocumentException
*/
public static Paragraph createParagraph(String content) throws IOException, DocumentException {
Font font = new Font(getBaseFont(), 12, Font.NORMAL);
Paragraph paragraph = new Paragraph(content, font);
paragraph.setAlignment(Element.ALIGN_LEFT);
// 设置左缩进
paragraph.setIndentationLeft(12);
// 设置右缩进
paragraph.setIndentationRight(12);
// 设置首行缩进
paragraph.setFirstLineIndent(24);
// 行间距
paragraph.setLeading(20f);
// 设置段落上空白
paragraph.setSpacingBefore(5f);
// 设置段落下空白
paragraph.setSpacingAfter(10f);
return paragraph;
}
/**
* 表格内容
* @param content
* @return
* @throws IOException
* @throws DocumentException
*/
public static PdfPCell createCell(String content) throws IOException, DocumentException {
PdfPCell cell = new PdfPCell();
cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
cell.setHorizontalAlignment(Element.ALIGN_CENTER);
Font font = new Font(getBaseFont(), 12, Font.NORMAL);
cell.setPhrase(new Phrase(content, font));
return cell;
}
/**
* 字体
* @return
* @throws IOException
* @throws DocumentException
*/
public static BaseFont getBaseFont() throws IOException, DocumentException {
return BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment