项目中需要做导出功能,要支持excel,pdf导出。
excel导出我选择使用poi;pdf导出我选择使用iText,在此单独做记录。
先说说在设计与开发中的问题,从整体上把握设计思路。
思路(一)
在页面json拼装数据,在后台导出pdf文件到客户端。
本例子只是简单的导出列表数据,没有涉及到图片等其他复杂格式文件。所以还是比较简单的。
这个设计思路是最理想的。
在后台获取前台数据,把这些数据直接生成pdf文件流输出到response中去,
不会在服务器留下垃圾文件。在客户端会弹出文件保存框,直接保存到客户端本地。
-------------------
这个思路很好,但是在导出到客户端时我遇到问题,就是弹不出文件保存框,页面没什么反应。用ajax回调函数
弹出返回数据是一堆乱码。
基于此原因,我改用
思路(二)
把pdf文件生成在服务器下的一个目录下,在ajax回调函数中使用这个拼装成访问路径,
这样可以下载文件。如果浏览器总是弹出阻止下载文件的弹出提示,可以在浏览器工具--internet 选项--
安全--自定义级别--下载,改一下:文件下载:启用;文件下载的自动提示:启用。都是启用就可以了,
这样就不会在弹出了。
这样也有问题,1会在服务器下生成许多垃圾文件,需要维护人员定期的删除,不然硬盘就不够用了。
2在客户端访问生成的文件会是zip文件或者是没有后缀的文件格式,或者直接在浏览器直接打开了。
如果是zip或者是其他格式不被浏览器识别,解决问题的方法就是在web.xml中设置mime类型。
这个就不细说了,网上一大堆。如果直接在浏览器打开pdf文件,那可以在你电脑安装的pdf阅读器设置里
把在浏览器中打开这一项去掉。
这样还是会有问题:
1,web.xml设置的mime类型对整个工程都是有效地,在这里我想让浏览器下载这个类型的文件而不是打开,所以
我设置了mime;而在其他地方就是需要浏览器打开这个类型的文件提供在线阅读,而不是弹出下载的文件选择框。
所以设置mime类型是会发生冲突的。
2,在pdf阅读器设置取消掉“在浏览器打开”这一项不太符合用户习惯,用户使用这个功能还需要设置自己电脑上的其他
软件,这个太不合理了。
这样的问题,我决定改变访问方式,使用下载,而不是直接给文件在服务器的地址直接访问。
思路(三)
可以在服务器路径下生成pdf文件,对于访问方式采用下载方式,下载完成后再删除此文件。
这和思路(一)区别不是很大,之所以采用这种方式,是因为在设置文件类型时,
用代码设置response.setContentType("application/pdf");
response.addHeader("Content-Disposition","attachment;filename="+serfilename.trim());
serfilename是生成的临时pdf文件的名字,随机的,这两行代码必须在调用输入输出流之前,
因为只要一调用流往客户端写文件,就会弹出文件保存框,这两行代码还没走到,所以是无效的。
如果写在调用流之前,这个文件的名字是在调用流之后才生成的文件名。
所以,读写的逻辑自己定。
你的方法如果能封装OutpuStream,那就把response对象也传入你的方法中,并在调用流之前先调用这两行代码。
如果你的方法不能封装OutpuStream,那就先把文件写在服务器下路径,生成文件后,调用这两行代码,
然后自己再写读写文件到response。只要保证在读写流调用前就可以。
所以思路(三)和思路(一)是差不多的。
------------------
总之,
1,在web.xml中不要设置mime,在程序中能控制的就不要在控制全局的web.xml中设置。
2,文件的访问最好用下载方式,不要直接贴个url做成链接。
3,不要在服务器下生成垃圾文件。临时的文件用过后要删除。最好别生成临时文件。
-------------------
pdf导出我采用方式(三),生成临时文件,下载后删除。
excel导出我采用方式(一),直接写到客户端。
这是最后的代码,采用servlet方式。
web.xml 注意注释掉的部分
<servlet>
<description>ExportExcelServletDescription</description>
<display-name>ExportExcelServlet</display-name>
<servlet-name>ExportExcelServlet</servlet-name>
<servlet-class>org.hd.report.serv.ExportExcelServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ExportExcelServlet</servlet-name>
<url-pattern>/ExportExcelServlet</url-pattern>
</servlet-mapping>
<servlet>
<description>ExportPdfServletDescription</description>
<display-name>ExportPdfServlet</display-name>
<servlet-name>ExportPdfServlet</servlet-name>
<servlet-class>org.hd.report.serv.ExportPdfServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ExportPdfServlet</servlet-name>
<url-pattern>/ExportPdfServlet</url-pattern>
</servlet-mapping>
<!--
<mime-mapping>
<extension>doc</extension>
<mime-type>application/msword</mime-type>
</mime-mapping>
<mime-mapping>
<extension>docx</extension>
<mime-type>application/vnd.openxmlformats-officedocument.wordprocessingml.document</mime-type>
</mime-mapping>
<mime-mapping>
<extension>xls</extension>
<mime-type>application/msexcel</mime-type>
</mime-mapping>
<mime-mapping>
<extension>xlsx</extension>
<mime-type>application/vnd.openxmlformats-officedocument.spreadsheetml.sheet</mime-type>
</mime-mapping>
<mime-mapping>
<extension>pdf</extension>
<mime-type>application/pdf</mime-type>
</mime-mapping>
-->
pdf
package org.hd.report.serv;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.hd.util.ExportExcelUtil;
import org.hd.util.ExportPdfUtil;
/**
* Servlet implementation class PdfItextServlet
*/
public class ExportPdfServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
public ExportPdfServlet() {
super();
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request,response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
downLoadPdfService(request,response);
}
protected void downLoadPdfService(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8");
// response.setContentType("text/xml");
String thename = request.getParameter("dd") != null ? request.getParameter("dd") : "";
String resjson= request.getParameter("resjson") != null ? request.getParameter("resjson").trim() : "";
resjson=java.net.URLDecoder.decode(resjson,"UTF-8");
System.out.println("resjson from page--"+resjson);
String clientFileName="";
String pdfonserver=ExportPdfUtil.createPdfWithJson(resjson);
// String pdfonserver= request.getParameter("pdfonserver") != null ? request.getParameter("pdfonserver") : "";
pdfonserver=java.net.URLDecoder.decode(pdfonserver,"UTF-8");
String serfilename=pdfonserver.substring(pdfonserver.lastIndexOf("/")+1);//xx.pdf
//如果是变生成文件,边写入输出流到servlet,客户端会在输出流写入的时候就弹出保存文件框,setContentType,addHeader所以必须在输出流之前调用。
// response.setContentType("octets/stream");
response.setContentType("application/pdf");
// response.setContentType("application/x-msdownload");//对pdf这个也可以
response.addHeader("Content-Disposition","attachment;filename="+serfilename.trim());
String wholeServerPath=ExportPdfUtil.TEMP_PDF_PATH+"\\"+serfilename;
File fileOnServer=new File(wholeServerPath.trim());
if(!fileOnServer.exists()){
System.out.println("文件未找到。");
}else{
InputStream is=new BufferedInputStream(new FileInputStream(fileOnServer));
OutputStream os=new BufferedOutputStream(response.getOutputStream());
byte[] buf=new byte[1024];
while((is.read(buf))!=-1){
os.write(buf);
os.flush();
}
if(os!=null){
os.flush();
os.close();
}
if(is!=null){
is.close();
}
if(fileOnServer.exists()){
boolean flag=fileOnServer.delete();
if(flag){
System.out.println(fileOnServer.getPath()+"完成删除。");
}
}
}
}
}
excel
package org.hd.report.serv;
import java.io.IOException;
import java.io.OutputStream;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.hd.util.ExportExcelUtil;
/**
* Servlet implementation class PdfItextServlet
*/
public class ExportExcelServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
public Expor