如何在java中为动态生成的文件提供下载选项

时间:2014-02-11 04:48:05

标签: java servlets jasper-reports

我正在使用jasper报告创建pdf文件。生成pdf文件的代码运行正常,文件在指定的路径上创建。但是我想要下载文件而不是存储在客户端的某个驱动器上。我在我的问题中动态使用word,因为它是在用户点击下载时从jasper报告生成的。我搜索了这个,我得到了响应.setHeader负责下载,但它需要一个源或我们可以说存储的路径。生成pdf的代码如下所示。

String ip="D:\\workspace\\Jsaper1\\src\\Coll.jasper";
    String op="D:\\workspace\\Jsaper1\\src\\Timesheet.pdf";


    try
    {
        File file=new File(ip);
        InputStream is=new FileInputStream(file);
         Map<String, Object> params = new HashMap<String, Object>();
        Datasource da=new Datasource();
        JRDataSource jrdsource=new JRBeanCollectionDataSource(da.getDataSource());


        JasperReport jreport=(JasperReport) JRLoader.loadObject(file);

        JasperPrint jasperPrint = JasperFillManager.fillReport(jreport, params, da.getDataSource1());

        JasperExportManager.exportReportToPdfFile(jasperPrint, op);   

                sos.flush();
        sos.close();
    }
    catch(Exception e)
    {
        e.printStackTrace();
    }

5 个答案:

答案 0 :(得分:0)

由于生成的文件已经写入磁盘,您可以打开它然后写入响应“OutputStream”。使用Apache的IOUtils#copy将输入流的内容复制到输出流,避免使用样板。它还可以进行内部缓冲,因此无需用InputStream包裹BufferedInputStream

public class DownloadServlet extends HttpServlet{
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setContentType("application/octet-stream; charset=windows-1252");
        response.setHeader("Content-Disposition", "attachment; filename=" + fileName);

        InputStream input = null;
        OutputStream output = null;

        try {
            input = new FileInputStream(new File("file-path-where-generated-pdf-is-stored"));
            output = response.getOutputStream();

            IOUtils.copy(input, output);

            output.flush();
        } catch (IOException e) {
            //log it
        } finally{
            close(input);
            close(output);

            input = null;
            output = null;
        }
    }

    //Right way to close resource
    public static void close(Closeable c) {
        if (c == null) return; 
        try {
            c.close();
        }catch (IOException e) {
            //log it
        }
    }
}

答案 1 :(得分:0)

以下是您的解决方案

在html / Interface文件中插入此代码。你可以这样做:

response.setContentType("application/pdf");
response.setHeader("Content-Disposition", "attachment; filename=output.pdf");
ServletOutputStream sosStream = response.getOutputStream();
JasperPrint jasperPrint = (JasperPrint) session.getAttribute("jasperPrint");
JasperExportManager.exportReportToPdfStream(jasperPrint, sosStream);
File tempFile = File.createTempFile("TempFile.pdf",".tmp",new File("."));
InputStream isStream = null;
isStream = new FileInputStream(tempFile);
int ibit = 256;
while ((ibit) >= 0)
 {
            ibit = isStream.read();
            sosStream.write(ibit);
 }
sosStream.flush();
sosStream.close();
isStream.close();
out.clear();
out = pageContext.pushBody();

备注: - 1.设置响应内容类型和标头。 2.您可以在会话中设置jasperprint并检索它。 3.动态调用JasperExportManager.exportReportToPdfStream。这将创建一个pdf的outpoutstream。 其余的代码确实将作业从流写入临时文件。

您可以通过点击下载按钮来调用此代码,然后会出现下载文件弹出窗口,询问保存位置。

答案 2 :(得分:0)

尝试使用以下示例作为参考

ByteArrayOutputStream baos = new ByteArrayOutputStream();
JRAbstractExporter exporter = new JRPdfExporter();
exporter.setParameter(JRExporterParameter.OUTPUT_STREAM, baos);
ByteArrayOutputStream baos = exporter.exportReport();
OutputStream os = null;

try {
   response.setContentType(mimeType);
   response.setHeader("Content-disposition", "attachment; filename=\"Timesheet.pdf");
   response.setHeader("Expires", "0");
   response.setHeader("Cache-Control", "must-revalidate, post-check=0, pre-check=0");
   os = response.getOutputStream();
   response.setContentLength(baos.size());

   baos.writeTo(os);
  }  finally {
        os.flush();
        os.close();
}

答案 3 :(得分:0)

请在报表方法中使用ByteArrayOutputStream obj,我已在动态报表(Jasper Api)中实现,它为我工作: -

@RequestMapping(value="/pdfDownload", method = RequestMethod.GET)
public void getPdfDownload(HttpServletResponse response) {
ByteArrayOutputStream buffer = new ByteArrayOutputStream();

report().columns().setDataSource().show()
.toPdf(buffer);

byte[] bytes = buffer.toByteArray();
InputStream inputStream = new ByteArrayInputStream (bytes);
IOUtils.copy(inputStream, response.getOutputStream());
response.setHeader("Content-Disposition", "attachment; filename=Accepted1.pdf");
response.flushBuffer();

}

答案 4 :(得分:0)

您可以使用以下代码。这是使用java servlet的完整示例

我添加了以下代码。您可以使用以下代码从servlet下载pdf文件..

  1. 请下载以下jar文件 请下载bellow jar文件

    1. jasperreports-5.0.1.jar
    2. commons-logging-1.1.2.jar
    3. commons-digester-2.1.jar
    4. commons-collections-3.2.1-1.0.0.jar
    5. commons-beanutils-1.8.3.jar
    6. groovy-all-2.1.3.jar
    7. com.lowagie.text-2.1.7.jar
    8. your database library
    
  2. 现在在doGet

    中的servlet中使用下面的代码
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {   
    try {
        String path = "D:\\Software\\iReport-5.0.0-windows-installer\\u\\report4.jrxml";
        JasperReport jasReport = JasperCompileManager.compileReport(path);
        System.out.println("Jasper Report : " + jasReport);
         //Database connection
        Connection con = /*Your Datase Connection*/ ;
        System.out.println(con);
        //If You have paramerter add here
        Map paramMap = new HashMap();
        paramMap.put("id", request.getParameter("id"));
    
        //if your have any parmeter add null to paramMap
        JasperPrint jasPrint = JasperFillManager.fillReport(jasReport, null, con); //, mapParam, con);
        System.out.println("Jasper Print : " + jasPrint);
    
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
    
        response.setContentType("application/x-download");
        response.addHeader("Content-disposition", "attachment; filename=creditcard.pdf");
        ServletOutputStream sos = response.getOutputStream();
        JasperExportManager.exportReportToPdfStream(jasPrint, sos);
    
    } catch (JRException ex) {
        Logger.getLogger(Tests.class.getName()).log(Level.SEVERE, null, ex);
      }
    }