【问题标题】:How to download the PDF in Jquery ajax call using java如何使用java在Jquery ajax调用中下载PDF
【发布时间】:2019-11-04 07:56:18
【问题描述】:

我创建了一个下载 PDF 文件的服务。

在我的服务器端 (Java) 上,PDF 已成功生成。但我无法在 UI 端下载它(使用 Jquery Ajax 调用)。

谁能帮我解决这个问题?

$(document).on('click', '.orderView', function(event){
    orderId = $(this).attr('data');
    $.ajax({
        type : 'GET',
        contentType : 'application/json',
        url : '../service/purchase/generateInventoryPurchasePdf/'+orderId,
        success : function(response) {
            console.log("Success");
        },
        error : function(response) {
            console.log("Error :" + response);
        }
    });

}); 

Java 代码:

@RequestMapping(value = "/generateInventoryPurchasePdf/{purchaseId}", method = RequestMethod.GET)
public ResponseEntity<ByteArrayResource> generateInventoryPurchasePdf(HttpServletResponse response,@PathVariable("purchaseId") Long purchaseId) throws Exception {

PurchaseOrder purchaseOrder = null;
    purchaseOrder = purchaseService.findByPurchaseOrderId(purchaseId);

    // generate the PDF
    Map<Object,Object> pdfMap = new HashMap<>();
    pdfMap.put("purchaseOrder", purchaseOrder);
    pdfMap.put("purchaseOrderDetail", purchaseOrder.getPurchaseOrderDetail());
    pdfMap.put("vendorName", purchaseOrder.getInvVendor().getName());
    pdfMap.put("vendorAddrs", purchaseOrder.getInvVendor().getVenAddress().get(0));
    File file = util.generatePdf("email/purchasepdf", pdfMap);

    MediaType mediaType = MediaTypeUtils.getMediaTypeForFileName(this.servletContext, file.getName());
    System.out.println("fileName: " + file.getName());
    System.out.println("mediaType: " + mediaType);

    //Path path = Paths.get(file.getAbsolutePath() + "/" + file.getName());
    Path path = Paths.get(file.getAbsolutePath());
    byte[] data = Files.readAllBytes(path);
    ByteArrayResource resource = new ByteArrayResource(data);

    return ResponseEntity.ok()
            // Content-Disposition
            .header(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=" + path.getFileName().toString())
            // Content-Type
            .contentType(mediaType) //
            // Content-Lengh
            .contentLength(data.length) //
            .body(resource);
}

mediaUtil 类:

public class MediaTypeUtils {

    public static MediaType getMediaTypeForFileName(ServletContext servletContext, String fileName) {

        // application/pdf
        // application/xml
        // image/gif, ...
        String mineType = servletContext.getMimeType(fileName);
        try {
            MediaType mediaType = MediaType.parseMediaType(mineType);
            return mediaType;
        } catch (Exception e) {
            return MediaType.APPLICATION_OCTET_STREAM;
        }
    }
}

PDF 生成代码:

public File generatePdf(String templateName, Map<Object, Object> map) throws Exception {
    Assert.notNull(templateName, "The templateName can not be null");
    Context ctx = new Context();
    if (map != null) {
        Iterator<Entry<Object, Object>> itMap = map.entrySet().iterator();
        while (itMap.hasNext()) {
            Map.Entry<Object, Object> pair = itMap.next();
            ctx.setVariable(pair.getKey().toString(), pair.getValue());
        }
    }
    String processedHtml = templateEngine.process(templateName, ctx);
    FileOutputStream os = null;
    String fileName = "POLIST";
    try {
        final File outputFile = File.createTempFile(fileName, ".pdf",new File(servletContext.getRealPath("/")));

        outputFile.mkdir();
        os = new FileOutputStream(outputFile);
        ITextRenderer renderer = new ITextRenderer();
        renderer.setDocumentFromString(processedHtml);
        renderer.layout();
        renderer.createPDF(os, false);
        renderer.finishPDF();
        System.out.println("PDF created successfully");
        return outputFile;
    } finally {
        if (os != null) {
            try {
                os.close();
            } catch (IOException e) { 
            }
        }
    }
}

我没有收到任何错误,PDF 在服务器端成功生成。但在 UI 方面不起作用。

【问题讨论】:

标签: javascript java jquery spring-boot


【解决方案1】:

通过 AJAX 下载文件并不是一件合乎逻辑的事情。当您进行 AJAX 调用时,从服务器返回的数据将返回到您页面的 JavaScript 代码中(在 response 回调值中),而不是返回到浏览器本身来决定要做什么。因此浏览器无法启动下载,因为浏览器不能直接控制响应——而是由您的 JavaScript 代码控制。

正如您在问题下方的评论中指出的那样,您可以使用一些解决方法,但实际上最好的方法是使用常规的非 AJAX 请求进行下载

例如,您可以将 jQuery 代码替换为

$(document).on('click', '.orderView', function(event){
    orderId = $(this).attr('data');
    window.open('../service/purchase/generateInventoryPurchasePdf/'+orderId);
});

这将从新选项卡下载文档,而不会离开当前页面。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-11-26
    • 2016-04-07
    • 2016-12-28
    • 1970-01-01
    • 2014-04-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-09
    相关资源
    最近更新 更多