Java如何实现Pdf的导出?
在某些场景中,我们需要从数据库或其他来源获取的数据信息,动态的导出Pdf文件,如准考证的打印等。这时我们需要借助第三方依赖包—itextpdf 来实现此需求。
一、制作PDF模板
1、在Word内制作模板
因为PDF常用的软件不支持编辑,所以先用Word工具,如WPS或者Office新建一个空白Word文档,里面制作出自己想要的样式。
2、将Word转换成PDF形式
将设置好的Word文档转换成PDF形式,保存起来。
3、编辑PDF准备表单
用Adobe Acrobat DC 软件打开保存好的PDF模板文件,点击右下角的更多工具按钮
进入到此页面,点击“准备表单”按钮。
接下来进行详细的配置数据源(注意,配置的数据源字段必须与Java中的实体类对象的字段名保持一致)
另外注意:在要显示图像的区域,点击鼠标右键,选择文本域,设定好图像的显示位置,并指定数据源字段
配置完成之后保存,留作模板使用。
二、编写代码
在准备好PDF模板之后,即可以开始编写代码来实现PDF的导出
1、导入依赖
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itextpdf</artifactId>
<version>5.5.13</version>
</dependency>
2、实体类
import lombok.Data;
@Data
public class AdmissionCard {
private String no;
private String name;
private String sex;
private String idCard;
private String school;
private String enterSchool;
private String major;
private String enterName;
private String examAddress;
}
3、Service层代码的实现
public interface PdfCustomService {
void generatorAdmissionCard(AdmissionCard admissionCard, HttpServletResponse response) throws UnsupportedEncodingException, FileNotFoundException;
}
import cn.ecut.file.pdf.entity.AdmissionCard;
import cn.ecut.file.pdf.service.PdfCustomService;
import com.itextpdf.text.Document;
import com.itextpdf.text.Image;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;
@Service
@Slf4j
public class PdfCustomServiceImpl implements PdfCustomService {
@Override
public void generatorAdmissionCard(AdmissionCard admissionCard, HttpServletResponse response) throws UnsupportedEncodingException, FileNotFoundException {
String templateName = "准考证-模板.pdf";
String path = "";
String systemName = System.getProperty("os.name");
if(systemName.toUpperCase().startsWith("WIN")){
path = "D:/pdf/";
}else {
path = "/usr/local/pdf/";
}
String fileName = admissionCard.getName() + "-硕士准考证.pdf";
fileName = URLEncoder.encode(fileName, "UTF-8");
response.setContentType("application/force-download");
response.setHeader("Content-Disposition",
"attachment;fileName=" + fileName);
OutputStream out = null;
ByteArrayOutputStream bos = null;
PdfStamper stamper = null;
PdfReader reader = null;
try {
out = response.getOutputStream();
reader = new PdfReader(path + templateName);
bos = new ByteArrayOutputStream();
stamper = new PdfStamper(reader, bos);
AcroFields form = stamper.getAcroFields();
BaseFont font = BaseFont.createFont("C:/WINDOWS/Fonts/SIMSUN.TTC,1", BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
form.addSubstitutionFont(font);
Map<String, Object> data = new HashMap<>(15);
data.put("no", admissionCard.getNo());
data.put("name", admissionCard.getName());
data.put("sex", admissionCard.getSex());
data.put("idCard", admissionCard.getIdCard());
data.put("school", admissionCard.getSchool());
data.put("enterSchool", admissionCard.getEnterSchool());
data.put("examAddress", admissionCard.getExamAddress());
data.put("major", admissionCard.getMajor());
data.put("enterName", admissionCard.getEnterName());
data.put("studentImg", admissionCard.getStudentImg());
for(String key : data.keySet()){
if("studentImg".equals(key)){
int pageNo = form.getFieldPositions(key).get(0).page;
Rectangle signRect = form.getFieldPositions(key).get(0).position;
float x = signRect.getLeft();
float y = signRect.getBottom();
String studentImage = data.get(key).toString();
Image image = Image.getInstance(studentImage);
PdfContentByte under = stamper.getOverContent(pageNo);
image.scaleToFit(signRect.getWidth(), signRect.getHeight());
image.setAbsolutePosition(x, y);
under.addImage(image);
}
else {
form.setField(key, data.get(key).toString());
}
}
stamper.setFormFlattening(true);
stamper.close();
Document doc = new Document();
PdfCopy copy = new PdfCopy(doc, out);
doc.open();
PdfImportedPage importPage = copy.getImportedPage(new PdfReader(bos.toByteArray()), 1);
copy.addPage(importPage);
doc.close();
log.info("*****************************PDF导出成功*********************************");
}catch (Exception e){
e.printStackTrace();
}finally {
try {
if (out != null) {
out.flush();
out.close();
}
if (reader != null) {
reader.close();
}
}catch (Exception e){
e.printStackTrace();
}
}
}
}
4、Controller层的实现
import cn.ecut.file.pdf.entity.AdmissionCard;
import cn.ecut.file.pdf.service.PdfCustomService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletResponse;
import java.io.FileNotFoundException;
import java.io.UnsupportedEncodingException;
@RestController
@Api(value = "PDF相关操作接口", tags = "PDF相关操作接口")
@RequestMapping("/pdf")
public class PdfController {
@Autowired
private PdfCustomService pdfCustomService;
@ApiOperation(value = "导出PDF")
@PostMapping("/admissioncard")
public void generatorAdmissionCard(@RequestBody AdmissionCard admissionCard, HttpServletResponse response){
try {
pdfCustomService.generatorAdmissionCard(admissionCard, response);
} catch (UnsupportedEncodingException | FileNotFoundException e) {
e.printStackTrace();
}
}
}
三、测试效果
请求接口,动态传递数据从而导出不同数据的PDF文档
下载响应的PDF文档
结果正确,完美实现PDF的动态导出
|