PDFUtils

这个博客介绍了如何使用Java将PDF文件转换为Base64编码,同时警告了使用sun.misc.BASE64Encoder和BASE64Decoder的不安全性,建议使用Apache Commons Codec库的Base64类作为替代。还提供了相关的代码示例。

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

相关jar包

<dependency>
      <groupId>com.lowagie</groupId>
      <artifactId>itext</artifactId>
      <!--<exclusions>-->
      <!--<exclusion>-->
      <!--<groupId>*</groupId>-->
      <!--<artifactId>*</artifactId>-->
      <!--</exclusion>-->
      <!--</exclusions>-->
      <version>2.1.7</version>
</dependency>

 <dependency>
      <groupId>commons-lang</groupId>
      <artifactId>commons-lang</artifactId>
      <version>2.4</version>
    </dependency>
 <dependency>
      <groupId>com.itextpdf</groupId>
      <artifactId>itextpdf</artifactId>
      <version>5.5.13</version>
    </dependency>

import com.itextpdf.text.BaseColor;
import com.itextpdf.text.Font;
import com.itextpdf.text.pdf.*;
import com.lowagie.text.pdf.PdfCopy;
import com.lowagie.text.pdf.PdfImportedPage;
import com.lowagie.text.pdf.PdfReader;
import org.apache.commons.lang.StringUtils;
import org.apache.struts2.ServletActionContext;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**

  • Created by Gaci on 2020/7/28.
    /
    public class PDFUtils {
    /
    BASE64Encoder和BASE64Decoder这两个方法是sun公司的内部方法,并没有在java api中公开过,所以使用这些方法是不安全的,

    • 将来随时可能会从中去除,所以相应的应该使用替代的对象及方法,建议使用apache公司的API—可引用 import org.apache.commons.codec.binary.Base64;进行替换
      */
      static BASE64Encoder encoder = new BASE64Encoder();
      static BASE64Decoder decoder = new BASE64Decoder();

    public static void main(String[] args) throws Exception{
    //将PDF格式文件转成base64编码
    // String base64String = getPDFBinary(“E:\123.pdf”);
    // System.out.println(base64String);
    // base64String = base64String.replaceAll("\r","");
    // base64String = base64String.replaceAll("\t","");
    // base64String = base64String.replaceAll("\n","");
    // System.out.println(base64String);

// Integer a = new Integer(3);
// Integer b = 3;
// int c=3;
// System.out.println(a ==b);
// System.out.println(a ==c);
// Integer f1 =100,f2=100,f3=150,f4=150;
// System.out.println(f1 ==f2);
// System.out.println(f3 ==f4);

// int c=200;
// Integer d=200;
// System.out.println(c ==d);
// System.out.println(d.equals©);

    // 方式1:--start
    // 路径
    String path = "";
    // PDFbase64
    String URLBase = "";
    SimpleDateFormat sf = new SimpleDateFormat("yyyyMMddHHmmss");
    String fileName = "label_"+sf.format(new Date());
    String labelPathPdf = path + "/"+fileName +".pdf";
    File file = base64StringToPDF(URLBase,labelPathPdf);
    // controller,action  获取HttpServletResponse
    HttpServletResponse response = ServletActionContext.getResponse();
    // controller,action 调用
    OutputStream os = response.getOutputStream();// 取得输出流
    response.reset();// 清空输出流

    setResponsePdfHeader(response, fileName);
    pdfFilesAndResponse(file,os);
    // 方式1:--end

    // 方式2:--start
    List<String> fileNames1 = new ArrayList<String>();//存放pdf的url
    SimpleDateFormat sf1 = new SimpleDateFormat("yyyyMMddHHmmss");
    String fileName1 = "label2_" + sf1.format(new Date());
    String  pdfFilePath1 =  fileName +".pdf";//PDF文件名
    File pdfFile1 = new File(pdfFilePath1);// PDF文件

    //定义输出流
    HttpServletResponse response1= ServletActionContext.getResponse();
    OutputStream os1 = response.getOutputStream();// 取得输出流
    response.reset();// 清空输出流
    setResponseHeader(response1, fileName1);
    mergePdfFiles(fileNames1, pdfFile1);
    pdfFilesAndResponse(pdfFile1, os1);
    // 方式2:--end

}

/**
 * 将PDF转换成base64编码
 * 1.使用BufferedInputStream和FileInputStream从File指定的文件中读取内容;
 * 2.然后建立写入到ByteArrayOutputStream底层输出流对象的缓冲输出流BufferedOutputStream
 * 3.底层输出流转换成字节数组,然后由BASE64Encoder的对象对流进行编码
 * @param filePath
 * @return
 */
public static String getPDFBinary(String filePath) {
    FileInputStream fin =null;
    BufferedInputStream bin =null;
    ByteArrayOutputStream baos = null;
    BufferedOutputStream bout =null;
    try {
        //建立读取文件的文件输出流
        fin = new FileInputStream(new File(filePath));
        //在文件输出流上安装节点流(更大效率读取)
        bin = new BufferedInputStream(fin);
        // 创建一个新的 byte 数组输出流,它具有指定大小的缓冲区容量
        baos = new ByteArrayOutputStream();
        //创建一个新的缓冲输出流,以将数据写入指定的底层输出流
        bout = new BufferedOutputStream(baos);
        byte[] buffer = new byte[1024];
        int len = bin.read(buffer);
        while(len != -1){
            bout.write(buffer, 0, len);
            len = bin.read(buffer);
        }
        //刷新此输出流并强制写出所有缓冲的输出字节,必须这行代码,否则有可能有问题
        bout.flush();
        byte[] bytes = baos.toByteArray();
        //sun公司的API
        return encoder.encodeBuffer(bytes).trim();
        //apache公司的API
        //return Base64.encodeBase64String(bytes);

    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }finally{
        try {
            fin.close();
            bin.close();
            //关闭 ByteArrayOutputStream 无效。此类中的方法在关闭此流后仍可被调用,而不会产生任何 IOException
            //baos.close();
            bout.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    return null;
}

/**
 * 将base64编码转换成PDF,保存到
 * @param base64sString
 * 1.使用BASE64Decoder对编码的字符串解码成字节数组
 * 2.使用底层输入流ByteArrayInputStream对象从字节数组中获取数据;
 * 3.建立从底层输入流中读取数据的BufferedInputStream缓冲输出流对象;
 * 4.使用BufferedOutputStream和FileOutputSteam输出数据到指定的文件中
 */
public static void base64StringToPDF1(String base64sString,String filePath){
    BufferedInputStream bin = null;
    FileOutputStream fout = null;
    BufferedOutputStream bout = null;
    try {
        //将base64编码的字符串解码成字节数组
        byte[] bytes = decoder.decodeBuffer(base64sString);
        //apache公司的API
        //byte[] bytes = Base64.decodeBase64(base64sString);
        //创建一个将bytes作为其缓冲区的ByteArrayInputStream对象
        ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
        //创建从底层输入流中读取数据的缓冲输入流对象
        bin = new BufferedInputStream(bais);
        //指定输出的文件
        File file = new File(filePath);
        //创建到指定文件的输出流
        fout = new FileOutputStream(file);
        //为文件输出流对接缓冲输出流对象
        bout = new BufferedOutputStream(fout);

        byte[] buffers = new byte[1024];
        int len = bin.read(buffers);
        while(len != -1){
            bout.write(buffers, 0, len);
            len = bin.read(buffers);
        }
        //刷新此输出流并强制写出所有缓冲的输出字节,必须这行代码,否则有可能有问题
        bout.flush();

    } catch (IOException e) {
        e.printStackTrace();
    }finally{
        try {
            bin.close();
            fout.close();
            bout.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}



/**
 *  解码 PDF流
 * @param base64String  PDF流字符串
 * @param newFile   文件保存地址
 */
public static File base64StringToPDF(String base64String, String newFile) {
    File file = null;
    try {
        BASE64Decoder decoder = new BASE64Decoder();
        byte[] bytes = decoder.decodeBuffer(base64String);
        ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
        BufferedInputStream bin = new BufferedInputStream(bais);
        file = new File(newFile);
        FileOutputStream fout = new FileOutputStream(file);
        BufferedOutputStream bout = new BufferedOutputStream(fout);
        byte[] buffers = new byte[1024];
        int len = bin.read(buffers);
        while (len != -1) {
            bout.write(buffers, 0, len);
            len = bin.read(buffers);
        }
        bout.flush();
        bout.close();
    } catch (Exception e) {

        e.printStackTrace();
    }
    return file;

}

public static void createZip(List<String> fileNames, String fileName) throws Exception {
    File zipFile = new File(fileName + ".zip");
    //定义输出流
    HttpServletResponse response= ServletActionContext.getResponse();
    OutputStream os = response.getOutputStream();// 取得输出流
    response.reset();// 清空输出流
    setResponseZipHeader(response,fileName);
    zipFilesAndResponse(fileNames,zipFile,os);
}

public static void createPdf(List<String> fileNames,String fileName) throws Exception {
    if(!fileNames.isEmpty() && !StringUtils.isEmpty(fileName)) {
        File pdfFile = new File(fileName + ".pdf" );
        //定义输出流
        HttpServletResponse response = ServletActionContext.getResponse();
        OutputStream os = response.getOutputStream();// 取得输出流
        response.reset();// 清空输出流
        setResponsePdfHeader(response, fileName);
        mergePdfFiles(fileNames, pdfFile);
        pdfFilesAndResponse(pdfFile, os);
    }
}


/** 设置响应头 */
public static void setResponseZipHeader(HttpServletResponse response,String fileName) {
    try {
        response.setContentType("application/octet-stream;charset=UTF-8");
        response.setHeader("Content-Disposition", "attachment;filename="
                + java.net.URLEncoder.encode(fileName, "UTF-8")+".zip");
        response.addHeader("Pargam", "no-cache");
        response.addHeader("Cache-Control", "no-cache");
    } catch (Exception ex) {
        ex.printStackTrace();
    }
}

/** 设置响应头 */
public static void setResponseXlsHeader(HttpServletResponse response,String fileName) {
    try {
        response.setContentType("application/msexcel;charset=UTF-8");
        response.setHeader("Content-Disposition", "attachment;filename="
                + java.net.URLEncoder.encode(fileName, "UTF-8")+".xls");
        response.addHeader("Pargam", "no-cache");
        response.addHeader("Cache-Control", "no-cache");
    } catch (Exception ex) {
        ex.printStackTrace();
    }
}
/** 设置响应头 */
public static void setResponsePdfHeader(HttpServletResponse response,String fileName) {
    try {

// response.setContentType(“application/octet-stream;charset=UTF-8”);
response.setContentType(“application/pdf;charset=UTF-8”);
response.setHeader(“Content-Disposition”, “filename=”
+ java.net.URLEncoder.encode(fileName, “UTF-8”)+".pdf");
response.addHeader(“Pargam”, “no-cache”);
response.addHeader(“Cache-Control”, “no-cache”);
} catch (Exception ex) {
ex.printStackTrace();
}
}

/**
 * 输出excel文件
 * @param fileNames 临时文件名
 * @param out 输出流
 * @throws Exception
 */
public static void responseXlsFile(List<String> fileNames,OutputStream out)  throws Exception
{
    File srcFile = new File(fileNames.get(0));
    FileInputStream inStream = null;
    try
    {
        inStream = new FileInputStream(srcFile);
        byte[] buf = new byte[4096];
        int readLength;
        while (((readLength = inStream.read(buf)) != -1)) {
            out.write(buf, 0, readLength);
        }
        inStream.close();
        out.flush();
        out.close();
    }catch (Exception ex)
    {
        ex.printStackTrace();
        throw new Exception(ex.getMessage());
    }finally {
        if(inStream != null)
            inStream.close();
        if(out != null)
        {
            out.flush();
            out.close();
        }
        if(srcFile != null)  //删除临时文件
            if(srcFile.exists()) srcFile.delete();
    }
}

/**
 *压缩文件并输出到客户端
 * @param fileNames 需要压缩的文件名
 * @param zipFile  压缩文件
 * @param out   输出流
 * @throws Exception
 */
public static void zipFilesAndResponse(List<String> fileNames,File zipFile,OutputStream out) throws Exception
{
    File srcFiles[] = new File[fileNames.size()];
    for (int i = 0, n = fileNames.size(); i < n; i++) {
        srcFiles[i] = new File(fileNames.get(i));
    }
    FileInputStream inStream = null;
    try
    {
        ZipFiles(srcFiles, zipFile);
        inStream = new FileInputStream(zipFile);
        byte[] buf = new byte[4096];
        int readLength;
        while (((readLength = inStream.read(buf)) != -1)) {
            out.write(buf, 0, readLength);
        }
        inStream.close();
        out.flush();
        out.close();
    }catch (Exception ex)
    {
        ex.printStackTrace();
        throw new Exception(ex.getMessage());
    }finally {
        if(inStream != null)
            inStream.close();
        if(out != null)
        {
            out.flush();
            out.close();
        }
        if(zipFile.exists()) zipFile.delete();//删除压缩文件
        for(File srcFile:srcFiles)  //删除临时文件
            if(srcFile.exists()) srcFile.delete();
    }
}
/**
 *
 * @param srcFile 文件名数组
 * @param zipFile 压缩后文件
 */
public static void ZipFiles(java.io.File[] srcFile, java.io.File zipFile) throws Exception{
    byte[] buf = new byte[1024];
    try {
        ZipOutputStream out = new ZipOutputStream(new FileOutputStream(
                zipFile));
        for (int i = 0; i < srcFile.length; i++) {
            FileInputStream in = new FileInputStream(srcFile[i]);
            out.putNextEntry(new ZipEntry(srcFile[i].getName()));
            int len;
            while ((len = in.read(buf)) > 0) {
                out.write(buf, 0, len);
            }
            out.closeEntry();
            in.close();
        }
        out.close();
    } catch (IOException e) {
        e.printStackTrace();
        throw new Exception(e.getMessage());
    }
}

/**
 *PDF文件并输出到客户端
 * @param pdfFile  pdf文件
 * @param out   输出流
 * @throws Exception
 */
public static void pdfFilesAndResponse(File pdfFile, OutputStream out) throws Exception
{
    FileInputStream inStream = null;
    try
    {
        inStream = new FileInputStream(pdfFile);
        byte[] buf = new byte[4096];
        int readLength;
        while (((readLength = inStream.read(buf)) != -1)) {
            out.write(buf, 0, readLength);
        }
        inStream.close();
        out.flush();
        out.close();
    }catch (Exception ex)
    {
        ex.printStackTrace();
        throw new Exception(ex.getMessage());
    }finally {
        if(inStream != null)
            inStream.close();
        if(out != null)
        {
            out.flush();
            out.close();
        }
        if(pdfFile.exists()) pdfFile.delete();//删除压缩文件
    }
}

public static boolean mergePdfFiles(List<String> fileNames, File outfile) throws Exception {
    boolean retValue = false;
    com.lowagie.text.Document document = null;
    try {
        String[] files = new String[fileNames.size()];
        for(int i=0;i<fileNames.size();i++){
            files[i]= fileNames.get(i);
        }
        document = new com.lowagie.text.Document(new PdfReader(files[0]).getPageSize(1));
        PdfCopy copy = new PdfCopy(document, new FileOutputStream(outfile));
        document.open();
        for (int i = 0; i < files.length; i++) {
            PdfReader reader = new PdfReader(files[i]);
            int n = reader.getNumberOfPages();
            for (int j = 1; j <= n; j++) {
                document.newPage();
                PdfImportedPage page = copy.getImportedPage(reader, j);
                copy.addPage(page);
            }
        }
        retValue = true;
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        document.close();
    }
    return retValue;
}

/** 设置响应头 */
public static void setResponseHeader(HttpServletResponse response,String fileName) {
    try {
        response.setContentType("application/octet-stream;charset=UTF-8");
        response.setHeader("Content-Disposition", "attachment;filename="
                + java.net.URLEncoder.encode(fileName, "UTF-8") + ".pdf");
        response.addHeader("Pargam", "no-cache");
        response.addHeader("Cache-Control", "no-cache");
    } catch (Exception ex) {
        ex.printStackTrace();
    }
}

public static void AddContentToPDF(String pdfFile,String newPdfFile) throws Exception{
    //创建一个pdf读入流
    com.itextpdf.text.pdf.PdfReader reader = new com.itextpdf.text.pdf.PdfReader(pdfFile);
    //根据一个pdfreader创建一个pdfStamper.用来生成新的pdf.
    PdfStamper stamper = new PdfStamper(reader,
            new FileOutputStream(newPdfFile));

    //这个字体是itext-asian.jar中自带的 所以不用考虑操作系统环境问题.
    String realPath = AddContentToPDF.class.getResource("").toString();
    // msyh.ttf 是字体文件bai,就是微软雅黑,它是美du国微软公司委托中国北大zhi方正电子有限公司设计的一款全面支持daoClearType技术的字体。
    realPath = realPath.substring(5, realPath.indexOf("WEB-INF")) + "template/common/fonts/msyh.ttf";// 存放路径
    BaseFont bf = BaseFont.createFont(realPath, BaseFont.IDENTITY_H,BaseFont.NOT_EMBEDDED);
    //baseFont不支持字体样式设定.但是font字体要求操作系统支持此字体会带来移植问题.
    Font font = new Font(bf,10);
    font.setStyle(Font.BOLD);
    font.getBaseFont();
    //页数是从1开始的
    for (int i=1; i<=reader.getNumberOfPages(); i++){
        //获得pdfstamper在当前页的上层打印内容.也就是说 这些内容会覆盖在原先的pdf内容之上.
        PdfContentByte over = stamper.getOverContent(i);
        //用pdfreader获得当前页字典对象.包含了该页的一些数据.比如该页的坐标轴信息.
        PdfDictionary p = reader.getPageN(i);
        //拿到mediaBox 里面放着该页pdf的大小信息.
        PdfObject po =  p.get(new PdfName("MediaBox"));
        System.out.println(po.isArray());
        //po是一个数组对象.里面包含了该页pdf的坐标轴范围.
        PdfArray pa = (PdfArray) po;
        System.out.println(pa.size());
        //看看y轴的最大值.
        System.out.println(pa.getAsNumber(pa.size()-1));
        //开始写入文本
        over.beginText();
        //设置字体和大小
        over.setFontAndSize(font.getBaseFont(), 6);
        //设置字体颜色
        over.setColorFill(BaseColor.BLACK);

        String productName = "一二三四五六七八九十一二三四五六七八九十";
        String[] lines = new String[2];
        if (productName.length() > 10) {
            lines[0] = productName.substring(0, 10);
            lines[1] = productName.substring(10, productName.length());
        } else {
            lines[0] = productName;
            lines[1] = "";
        }
        if (i == 1) {
            //设置字体的输出位置
            over.setTextMatrix(200, 250);
            //要输出的text
            over.showText(lines[0]);
            //设置字体的输出位置
            over.setTextMatrix(200, 242);
            //要输出的text
            over.showText(lines[1]);
        } else if (i == 2){
            //设置字体的输出位置
            over.setTextMatrix(210, 180);
            //要输出的text
            over.showText(lines[0]);
            //设置字体的输出位置
            over.setTextMatrix(210, 172);
            //要输出的text
            over.showText(lines[1]);
        }
        over.endText();
    }

    stamper.close();
}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值