java代码实现导出或者下载xml、word、pdf、excel功能

java代码实现导出或者下载xml、word、pdf、excel功能

写在前面:将用户操作日志以xml、word、pdf、excel格式的文件导出。

1、导出xml

导出xml使用JAXB的注解实现,实体如下

import javax.xml.bind.annotation.*;
import java.util.List;

@XmlAccessorType(XmlAccessType.PROPERTY)
@XmlType(name = "", propOrder = {
        "title",
        "log"
})
@XmlRootElement(name = "Body")
public class Submit {

    private String title;

    protected List<LogX> logX;

    @XmlElementWrapper(name = "logList")
    public List<LogX> getLog() {
        return logX;
    }

    public void setLog(List<LogX> logX) {
        this.logX = logX;
    }

    @XmlElement(name = "title", required = true,nillable=true)
    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }
}

复制代码

LogX实体如下:

import javax.xml.bind.annotation.*;
import java.io.Serializable;


@XmlAccessorType(XmlAccessType.PROPERTY)
@XmlType(name = "", propOrder = {
        "username",
        "operationIp",
        "createTime",
        "operation",
        "content"
})
@XmlRootElement(name = "log")
public class LogX implements Serializable {

    private static final long serialVersionUID = 1L;

    protected String content;

    protected String createTime;

    protected String operation;

    protected String username;

    protected String operationIp;

    @XmlElement(name = "content", required = true,nillable = true)
    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }

    @XmlElement(name = "createTime", required = true,nillable = true)
    public String getCreateTime() {
        return createTime;
    }

    public void setCreateTime(String createTime) {
        this.createTime = createTime;
    }

    @XmlElement(name = "operation", required = true,nillable = true)
    public String getOperation() {
        return operation;
    }

    public void setOperation(String operation) {
        this.operation = operation;
    }

    @XmlElement(name = "username", required = true,nillable = true)
    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    @XmlElement(name = "operationIp", required = true,nillable = true)
    public String getOperationIp() {
        return operationIp;
    }

    public void setOperationIp(String operationIp) {
        this.operationIp = operationIp;
    }
}

复制代码

@XmlAccessorType:便于对象与xml文件之间的转换
@XmlType中:参数propOrder指定映射XML时的节点顺序,使用该属性时,必须列出JavaBean对象中的所有字段,否则会报错。
@XmlRootElement :xml 文件的根元素
@XmlElementWrapper:仅允许出现在集合属性上,使用该注解后,将会在原xml结点上再包装一层xml
@XmlElement:字段,方法,参数级别的注解。该注解可以将被注解的(非静态)字段,或者被注解的get/set方法对应的字段映射为本地元素,也就是子元素。参数 name用于指定映射时的节点名称,指定生成元素的名字,若不指定,默认使用方法名小写作为元素名;参数 required字段是否必须,默认为false;参数 nillable是否处理空数据,默认为false。
其他关于JAXB的注解,大家就根据需要自行百度一下~

        Submit submit = new Submit();
        submit.setTitle(date2Str + "_logs");
        //这里给loxList集合赋值
        List<LogX> logXList = new ArrayList<>();
        submit.setLog(logXList);
        JAXBContext jc = null;
        ByteArrayOutputStream stream = new ByteArrayOutputStream();
        String fileName = submit.getTitle() + ".xml";
        ByteArrayOutputStream bis = null;
        FileOutputStream fileOutputStream = null;
        try {
            jc = JAXBContext.newInstance(Submit.class);
            Marshaller marshaller = jc.createMarshaller();
            marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
            marshaller.setProperty(Marshaller.JAXB_FRAGMENT, true);
            marshaller.setProperty(Marshaller.JAXB_ENCODING, "UTF-8");
            StringWriter writer = new StringWriter();
            marshaller.marshal(submit, writer);
            String content = writer.toString().replaceAll(JoinConstant.JAXB_NILL_STR, "");
            byte[] bs = content.getBytes("UTF-8");
            File file2 = new File(fileName);
            fileOutputStream = new FileOutputStream(file2);
            file2.createNewFile();
            fileOutputStream.write(bs);
            fileOutputStream.close();
            download(file2, res);
        } catch (JAXBException e) {
            e.printStackTrace();
            throw new RuntimeException("xml生成出错", e);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        } catch (IOException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        } finally {
            try {
                if (null != bis) bis.close();
                if (null != stream) stream.close();
            } catch (IOException e) {
                e.printStackTrace();
                throw new RuntimeException(e);
            }
        }
    }
复制代码

涉及到的download方法如下:

private void download(File file, HttpServletResponse res) {
        String fileName = file.getName();
        res.setHeader("content-type", "application/octet-stream");
        res.setContentType("application/octet-stream;charset=UTF-8");
        res.setHeader("Content-Disposition", "attachment; filename=" + fileName);
        byte[] buff = new byte[1024];
        BufferedInputStream bis = null;
        OutputStream os = null;
        try {
            os = res.getOutputStream();
            bis = new BufferedInputStream(new FileInputStream(
                    new File(file.getAbsolutePath())));
            int i = bis.read(buff);
            while (i != -1) {
                os.write(buff, 0, buff.length);
                os.flush();
                i = bis.read(buff);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (bis != null) {
                try {
                    bis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
复制代码
2、导出word

使用freemarker技术在web后台导出word文档:
具体步骤为:

1、设计word模版
2、修改ftl模版
3、 填充数值,导出word模板
4、生成Word模板
生产word模版主要为:一个是把word文档另存为xml文档;然后把xml文档后缀改为ftl文档****
如下图,我所需要的模板为:
在这里插入图片描述
然后使用sublime打开后缀名为ftl的文件,通过sublime插件,将ftl文件格式化,然后找到如下图所示位置进行编辑
在这里插入图片描述
注意${log.xh}等其他的标签的修改

代码如下:

        Map<String, Object> beanParams = new HashMap<String, Object>();
        //这里给loglist集合赋值
        List<LogView> loglist = new ArrayList<>();
        String date2Str = DateSearchUtils.date2Str(new Date());
        beanParams.put("title", date2Str+"日志信息");
        beanParams.put("loglist", loglist);
        beanParams.put("attention", "请注意确保所有信息的正确性");
        WordExportUtil.WordExportUtil(request, response, WordExportUtil.WORD_2003, "日志信息列表导出", "templateFile.ftl", beanParams,getExcelDir());
    
复制代码

涉及到的WordExportUtil.WordExportUtil()方法如下:

    public static String WORD_2007 = "WORD_2007";
    public static String WORD_2003 = "WORD_2003";

    /**
     * 设置下载文件中文件的名称
     * @param filename
     * @param request
     * @return
     */
    public static String encodeFilename(String filename, HttpServletRequest request) {
        String agent = request.getHeader("USER-AGENT");
        try {
            if ((agent != null) && (-1 != agent.indexOf("MSIE"))) {
                String newFileName = URLEncoder.encode(filename, "UTF-8");
                newFileName = StringUtils.replace(newFileName, "+", "%20");
                if (newFileName.length() > 150) {
                    newFileName = new String(filename.getBytes("GB2312"), "ISO8859-1");
                    newFileName = StringUtils.replace(newFileName, " ", "%20");
                }
                return newFileName;
            }
            if ((agent != null) && (-1 != agent.indexOf("Mozilla")))
                return MimeUtility.encodeText(filename, "UTF-8", "B");
            return URLEncoder.encode(filename, "UTF-8");
        } catch (Exception ex) {
            return filename;
        }
    }
    /**
     * @param request  HttpServletRequest
     * @param response HttpServletResponse
     * @param version  Word_2003/Word_2007
     * @param docFileName 生成的doc临时文件名
     * @param templateFile  freemark模板文件名
     * @param beanParams  入参数据:  Map<String, Object>类型
     */
    public static void writeResponse(HttpServletRequest request, HttpServletResponse response, String version, String docFileName, String templateFile, Map<String, Object> beanParams,String getExcelDir) {
        writeResponse(request, response, version, "temp", docFileName, "template", templateFile, beanParams, getExcelDir);
    }

    /**
     * @param request  HttpServletRequest
     * @param response HttpServletResponse
     * @param version  Word_2003/Word_2007
     * @param docTempDir  生成的doc临时文件目录
     * @param docFileName 生成的doc临时文件名
     * @param templateDir 存放freemark模板的目录
     * @param templateFile freemark模板文件名
     * @param beanParams   入参数据:  Map<String, Object>类型
     */
    public static void writeResponse( HttpServletRequest request, HttpServletResponse response, String version, String docTempDir, String docFileName, String templateDir, String templateFile, Map<String, Object> beanParams,String getExcelDir) {
        Configuration config = new Configuration();
        ServletContext sc = request.getSession().getServletContext();
        InputStream is = null;
        File previewFile = null;
        try {
            config.setDirectoryForTemplateLoading(new File(getExcelDir));
            config.setObjectWrapper(new DefaultObjectWrapper());
            Template template = config.getTemplate(templateFile, "UTF-8");
            String date2Str = DateSearchUtils.date2Str(new Date());
            String docFileName1 = date2Str+"_logs";
            if (WORD_2007.equals(version)) {
                docFileName1 = encodeFilename(docFileName1 + ".docx", request);
            } else {
                docFileName1 = encodeFilename(docFileName1 + ".doc", request);
            }
            String docName = "D:\\join\\excel"+docFileName;
            FileOutputStream fos = new FileOutputStream(docName);
            Writer out = new OutputStreamWriter(fos, "UTF-8");
            template.process(beanParams, out);
            out.flush();
            out.close();
            previewFile = new File(docName);
            is = new FileInputStream(previewFile);
            response.reset();
            if (WORD_2007.equals(version)) {
                response.setContentType("application/vnd.openxmlformats-officedocument.wordprocessingml.document;charset=UTF-8");
            }else{
                response.setContentType("application/vnd.ms-word;charset=UTF-8");
            }
            response.addHeader("Content-Disposition", "attachment;filename="+docFileName1);
            byte[] b = new byte[1024];
            int len;
            while ((len=is.read(b)) >0) {
                response.getOutputStream().write(b,0,len);
            }
            response.getOutputStream().flush();
            response.getOutputStream().close();

        } catch (Exception e) {
            e.printStackTrace();
        }finally{
            if(is!=null){
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(previewFile!=null){
                previewFile.delete();
            }
        }
    }

复制代码
3、导出pdf
// 新建文件
            String date2Str = DateSearchUtils.date2Str(new Date());
            String fileName = date2Str + "_logs.pdf";
            Document document = new Document();
            File file = new File(fileName);
            PdfWriter.getInstance(document, new FileOutputStream(file));
            document.open();
            BaseFont bfChinese = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);// 中文字体
            com.itextpdf.text.Font FontChinese18 = new com.itextpdf.text.Font(bfChinese, 18, com.itextpdf.text.Font.BOLD);
            //设置名字
            Paragraph pg_bt = new Paragraph("日志列表", FontChinese18);
            pg_bt.setAlignment(Element.ALIGN_CENTER);
            document.add(pg_bt);
            // Font fontChineseBold = new Font(bfChinese, 14, Font.BOLD);//内容字体特殊加粗
            Font titleChinese = new Font(bfChinese, 18, Font.BOLD);// 标题字体
            //    Font noteChinese = new Font(bfChinese, 12, Font.BOLD);//设置内容加粗的区
            Font contenttitleChinese = new Font(bfChinese, 12, Font.BOLD);// 内容小标题字体
            //这里给logViews 集合赋值
            List<LogView> logViews = new ArrayList<>();
            // 每行加空白
            pg_bt = new Paragraph(" ", titleChinese);
            pg_bt.setAlignment(Element.ALIGN_LEFT);
            document.add(pg_bt);
            SimpleDateFormat start = new SimpleDateFormat("HH:mm");
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            PdfPTable table5 = new PdfPTable(2);
            int width5[] = {80, 20};
            table5.setWidths(width5);
            PdfPCell cell51 = new PdfPCell(new Paragraph("日志打印时间 :  " + sdf.format(new Date()), contenttitleChinese));
            PdfPCell cell52 = new PdfPCell(new Paragraph("", contenttitleChinese));
            cell51.setBorder(0);
            cell52.setBorder(0);
            table5.addCell(cell51);
            table5.addCell(cell52);
            table5.setHorizontalAlignment(Element.ALIGN_LEFT);
            document.add(table5);
            //加入空行
            Paragraph blankRow51 = new Paragraph(18f, " ", contenttitleChinese);
            document.add(blankRow51);
            int col = 6;
            PdfPTable table = new PdfPTable(col);
            BaseColor bc = new BaseColor(102, 204, 255);
            //设置表格占PDF文档100%宽度
            table.setWidthPercentage(100);
            table.setWidths(new int[]{8, 12, 15, 20, 15, 30});
            BaseColor lightGrey01 = new BaseColor(0xCC, 0xCC, 0xCC);
            PdfPCell cell0 = toPdfPCell("序号", Element.ALIGN_CENTER);
            cell0.setBackgroundColor(lightGrey01);
            table.addCell(cell0);
            PdfPCell cell1 = toPdfPCell("用户名", Element.ALIGN_CENTER);
            cell1.setBackgroundColor(lightGrey01);
            table.addCell(cell1);
            PdfPCell cell2 = toPdfPCell("访问ip", Element.ALIGN_CENTER);
            cell2.setBackgroundColor(lightGrey01);
            table.addCell(cell2);
            PdfPCell cell3 = toPdfPCell("创建时间", Element.ALIGN_CENTER);
            cell3.setBackgroundColor(lightGrey01);
            table.addCell(cell3);
            PdfPCell cell4 = toPdfPCell("操作", Element.ALIGN_CENTER);
            cell4.setBackgroundColor(lightGrey01);
            table.addCell(cell4);
            PdfPCell cell5 = toPdfPCell("日志内容", Element.ALIGN_CENTER);
            cell5.setBackgroundColor(lightGrey01);
            table.addCell(cell5);
            if (logViews.size() > 0) {
                for (LogView view : logViews) {
                    table.addCell(toPdfPCell(view.getXh(), Element.ALIGN_CENTER));
                    table.addCell(toPdfPCell(view.getUsername(), Element.ALIGN_CENTER));
                    table.addCell(toPdfPCell(view.getAccessEndIp(), Element.ALIGN_CENTER));
                    table.addCell(toPdfPCell(DateSearchUtils.longToDate(view.getCreateTime()), Element.ALIGN_CENTER));
                    table.addCell(toPdfPCell(view.getOperation(), Element.ALIGN_CENTER));
                    table.addCell(toPdfPCell(view.getContent(), Element.ALIGN_CENTER));
                }
            }
            document.add(table);
            document.close();
            download(file, res);
        } catch (DocumentException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
复制代码

涉及到的toPdfPCell()方法如下:

public PdfPCell toPdfPCell(String name, int align) throws DocumentException, IOException {
        BaseFont bfChinese = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);// 中文字体
        Font fontChinese = new Font(bfChinese, 12, Font.NORMAL);// 内容字体
        PdfPCell cell = new PdfPCell(new Paragraph(name, fontChinese));
        cell.setHorizontalAlignment(align);// 设置内容水平居中显示
        cell.setVerticalAlignment(Element.ALIGN_MIDDLE);  // 设置垂直居中
        return cell;
    }
复制代码
4、导出excel

参考地址:easypoi.mydoc.io/

5、所需的maven依赖为:
<dependency>
            <groupId>com.lowagie</groupId>
            <artifactId>itext</artifactId>
            <version>2.1.7</version>
        </dependency>
        <dependency>
            <groupId>com.itextpdf</groupId>
            <artifactId>itextpdf</artifactId>
            <version>5.5.1</version>
        </dependency>
        <dependency>
            <groupId>com.yulintu</groupId>
            <artifactId>common-excel</artifactId>
            <version>RELEASE</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>org.freemarker</groupId>
            <artifactId>freemarker</artifactId>
            <version>2.3.23</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jms</artifactId>
            <version>5.2.0.RELEASE</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>com.itextpdf</groupId>
            <artifactId>itext-asian</artifactId>
            <version>5.2.0</version>
        </dependency>
        <dependency>
            <groupId>javax.mail</groupId>
            <artifactId>mail</artifactId>
            <version>RELEASE</version>
        </dependency>
复制代码

效果图如下:

6、导出的xml格式的文件内容如下:

在这里插入图片描述

7、导出的word格式的文件内容如下:

在这里插入图片描述

8、导出的pdf格式的文件内容如下:

在这里插入图片描述

9、导出的excel格式的文件内容如下:

在这里插入图片描述

写在最后:可能在进行这个功能实现时,我所采用的方法并不是最合理的,大家一起学习嘛