itext操作pdf文档[通俗易懂]

itext操作pdf文档[通俗易懂]关于itext操作pdf文档pdf基本操作自己点击链接去看下就会了java使用itext生成pdf再不行,去看官方文档itextApi直接找到com.itextpdf.text.pdf这个包,看它的操作类现在我就说我在这里碰到了坑用户要执行下载pdf文件的操作返回ModelAndView给页面就行了,但是springboot中的pdf模板类AbstractPdfStamper…

大家好,欢迎来到IT知识分享网。

关于itext操作pdf文档

pdf基本操作

自己点击链接去看下就会了
java使用itext生成pdf
再不行,去看官方文档 itext Api
直接找到com.itextpdf.text.pdf这个包,看它的操作类
现在我就说我在这里碰到了坑

  1. 用户要执行下载pdf文件的操作
    返回ModelAndView给页面就行了,但是springboot中的pdf模板类AbstractPdfStamperView 只支持
    com.lowagie包下的 不支持itext5,所以只能换个方式
    自己创建一个模板类

AbstractIText5PdfView

import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.PageSize;
import com.itextpdf.text.pdf.PdfWriter;
import org.springframework.web.servlet.view.AbstractView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayOutputStream;
import java.io.OutputStream;
import java.util.Map;

/**
 * 这里就全部复制spring 的,然后引入的东西改成第5版的就行了
 * 代码 几乎不变,唯一变的是引用路径~。~ 没贴出来了,自己导入就能看见
 *
 * @author Ran
 */
public abstract class AbstractIText5PdfView extends AbstractView {
    public AbstractIText5PdfView() {
        setContentType("application/pdf");
    }

    @Override
    protected boolean generatesDownloadContent() {
        return true;
    }

    @Override
    protected final void renderMergedOutputModel(Map<String, Object> model,
                                                 HttpServletRequest request, HttpServletResponse response)
            throws Exception {
        // 获得流
        ByteArrayOutputStream baos = createTemporaryOutputStream();
        Document document = newDocument();
        PdfWriter writer = newWriter(document, baos);
        prepareWriter(model, writer, request);
        buildPdfMetadata(model, document, request);
        /*     document.open();*/
        buildPdfDocument(model, document, writer, request, response);
        /*  document.close();*/
        writeToResponse(response, baos);
    }

    protected Document newDocument() {
        return new Document(PageSize.A4);
    }

    protected PdfWriter newWriter(Document document, OutputStream os)
            throws DocumentException {
        return PdfWriter.getInstance(document, os);
    }

    protected void prepareWriter(Map<String, Object> model, PdfWriter writer,
                                 HttpServletRequest request) throws DocumentException {

        writer.setViewerPreferences(getViewerPreferences());
    }

    protected int getViewerPreferences() {
        return PdfWriter.ALLOW_PRINTING | PdfWriter.PageLayoutSinglePage;
    }

    protected void buildPdfMetadata(Map<String, Object> model,
                                    Document document, HttpServletRequest request) {
    }

    protected abstract void buildPdfDocument(Map<String, Object> model,
                                             Document document, PdfWriter writer, HttpServletRequest request,
                                             HttpServletResponse response) throws Exception;
}

最后再创建一个操作类,继承AbstractIText5PdfView,重写buildPdfDocument
其中设定文件头部,文件类型就多说了
pdfUtil为文件操作类,操作document writer 元素 model可以向里面传值,生成pdf可以引用
访问顺序为 controller层 return new ModelAndView(new PdfView(), model);>>
PdfView 设定文件头部和类型 >>PdfUtil 操作pdf元素>>最后关闭document writer
(因为不只是创建一个pdf文件,所以增加代码的复用性)


@Controller("PdfView")
public class PdfView extends AbstractIText5PdfView {
    @Override
    protected void buildPdfDocument(Map<String, Object> model, Document document, PdfWriter writer, HttpServletRequest request, HttpServletResponse response) throws Exception {
        String excelName = "download.pdf";
        response.setContentType("APPLICATION/OCTET-STREAM");
        response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(excelName, "UTF-8"));
        PdfUtil pdfUtil = new PdfUtil();
        pdfUtil.createContactsPDF(document, writer, model);
    }
}

其中要注意一点 因为是自己创建的pdf模板,所以pdf大小默认是A4纸大小,如果要修改:

  Rectangle tRectangle = new Rectangle(590, 420);
  document.setPageSize(tRectangle);
  1. 以上是对pdf的增加,如果要对pdf里面的扩展文件如单选框,文本域,请看一下操作
    对模板进行操作不需要过多操作document 元素,所以不需要继承pdf模板
    其中附件三字段顺序是要自己一个个试出来的
    Map<String, AcroFields.Item> fields = acroFields.getFields(); //获取所有页面文本域信息
    其中单选框按钮也可修改值 其中值可以是 1 2 || true false
    Adobe Acrobat Reader DC 可以修改单选框什么值代表选中
    》》》》》》》》》》》》》
    其中要注意的一点就是兼容性的问题,因为此项目的客户是香港客户,那边查看pdf通常用Adobe 进行查看,所以要注意字体的兼容性,AdobeSongStd-Light.otf字体
    像wps我没有看过,所以不知道
   @Autowired
    private ISysSecretarialFjService secretarialFjService;

    @RequestMapping(value = "/createFJ3Pdf", method = RequestMethod.GET)
    public Object createFJ3Pdf(HttpServletRequest request, HttpServletResponse response) throws IOException {
        String dataorgid = JwtUtil.getUserSystemData(DataBaseConstant.SYS_DATAORGID, null);
        String id = request.getParameter("id");

        /*获取附件三pdf字段顺序*/
        String path = SecretaryPDFController.class.getClassLoader().getResource("FJjson/FJ3.json").getPath();
        String s = ReadUtils.readJsonFile(path);
        Map<String, List<String>> JSONlist = (Map<String, List<String>>) JSONObject.parse(s);
        /* 获取附件三pdf内容 */
        QueryWrapper<SysSecretarialFj> wrapper = new QueryWrapper<>();
        wrapper.eq("secretarial_id", id);
        List<SysSecretarialFj> secretarialFjList = secretarialFjService.list(wrapper);

        OutputStream ouputStream = response.getOutputStream();
        /*本地模板*/
        String fileName = SecretaryPDFController.class.getClassLoader().getResource("FJ/FJ3.pdf").getPath();
        PdfReader reader;
        PdfStamper stamper;
        ByteArrayOutputStream bos;
        try {
            reader = new PdfReader(fileName);// 读取pdf模板
            bos = new ByteArrayOutputStream();
            stamper = new PdfStamper(reader, bos);
            AcroFields form = stamper.getAcroFields();
            for (int i = 1; i <= 11; i++) {
                /* page页面写入 */
                List<String> page = JSONlist.get("page" + i);
                SysSecretarialFj secretarialFj = null;
                for (SysSecretarialFj sec : secretarialFjList) {
                    if (sec.getPageNum().equals("" + i)) {
                        secretarialFj = sec;
                    }
                }
                Map<String, String> map = (Map<String, String>) JSONObject.parse(secretarialFj.toString());
                List<String> dataList = new ArrayList<String>();
                for (int j = 1; j <= 50; j++) {
                    for (Map.Entry<String, String> entries : map.entrySet()) {
                        if (("c" + j).equals(entries.getKey())) {
                            dataList.add(entries.getValue().equals("null") || entries.getValue() == null ? "" : entries.getValue());
                        }
                    }
                }

                String FontUrl = SecretaryPDFController.class.getClassLoader().getResource("PdfResource/AdobeSongStd-Light.otf").getPath();
                BaseFont baseFont1 = BaseFont.createFont(FontUrl, BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);  //不加粗
                form.addSubstitutionFont(baseFont1);//因为字体兼容的问题,所以改变填写的字体
                for (int j = 0; j < page.size(); j++) {
                   /* form.setFieldProperty(page.get(j), "textfont", baseFont1, null);*/
                    form.setField(page.get(j), dataList.get(j));  //存入顺序一样
                }
            }
            stamper.setFormFlattening(false);//如果为false那么生成的PDF文件还能编辑
            stamper.close();

            Document document = new Document();
            PdfCopy pdfCopy = new PdfCopy(document, ouputStream);
            document.open();
            pdfCopy.addDocument(new PdfReader(bos.toByteArray()));
            response.setHeader("Content-disposition", "formPDF");
            response.setHeader("Content-type", "application/pdf;charset=utf-8");
            response.setHeader("Content-disposition", "attachment;filename=formPDF.pdf");
            response.setHeader("Pragma", "No-cache");
            document.close();
        } catch (BadPdfFormatException e) {
            e.printStackTrace();
        } catch (DocumentException e) {
            e.printStackTrace();
        } finally {
            if (ouputStream != null) {
                ouputStream.close();
            }
        }
        Result<String> res = new Result<>();
        res.setSuccess(true);
        return res;
    }

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://yundeesoft.com/26001.html

(0)

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信