春季无法使用wkhtmltopdf将html页面生成为pdf

时间:2018-08-28 10:17:42

标签: spring spring-boot pdf-generation thymeleaf wkhtmltopdf

在我最近的春季项目中,我需要从html页面生成pdf文件。我正在尝试使用WkhtmlToPdf来完成此任务。但是我无法从html页面生成pdf文件。我搜索了许多有关WkhtmlToPdf的项目和教程,但没有找到任何答案。我在这里发布我的代码。 这是我的Controller类,它重定向到带有学生列表的html页面

@Controller
public class TestController {

    @Autowired
    StudentService studentService;

    @Autowired
    PdfDemo pdfDemo;

    @GetMapping("/test")
    private String testPage(Model model)
    {    
        List<Student> studentList = studentService.findAll();
        System.out.println(studentList);
       model.addAttribute(studentList);
        return "sample";
    }
}

这是我的html页面,显示学生列表

<body>
<div class="container" id="pdfDiv">
    <h2>HTML Table</h2>
    <table class="table table-striped">
        <tr>
            <th>Id</th>
            <th>Name</th>
            <th>Session</th>
            <th>Department</th>
            <th>Roll</th>
            <th>Mobile</th>
        </tr>
        <tr th:each="student : ${studentList}">
            <td th:text="${student.id}"></td>
            <td th:text="${student.name}"></td>
            <td th:text="${student.session}"></td>
            <td th:text="${student.department}"></td>
            <td th:text="${student.roll}"></td>
            <td th:text="${student.mobile}"></td>
        </tr>
    </table>
</div>
<a href="#" th:href="@{/getStudentsListAsPdf}">Download PDF</a>
</body>

在这里您可以看到,我有一个生成pdf的链接。 PdfGenerateController类是

@Controller
public class PdfGenerateController {

    @GetMapping("/getStudentsListAsPdf")
    public ResponseEntity<Resource> generateReportOfStudent() {

        String downloadFilePath = generatePdfListForStudents();
        System.out.println("DL File Path: "+downloadFilePath);
        if (downloadFilePath == null)
            throw new NullPointerException("data missing");

        if (downloadFilePath == null)
            return ResponseEntity.badRequest()
                    .contentType(MediaType.parseMediaType("application/pdf"))
                    .body(null);

        File file = new File(downloadFilePath);

        Path path = Paths.get(file.getAbsolutePath());
        ByteArrayResource resource = null;
        try {
            resource = new ByteArrayResource(Files.readAllBytes(path));
        } catch (IOException e) {
            e.printStackTrace();
        }

        HttpHeaders headers = new HttpHeaders();
        headers.add("Content-Disposition", "attachment; filename=\"student_list" + ".pdf\"");

        return ResponseEntity.ok()
                .headers(headers)
                .contentLength(file.length())
                .contentType(MediaType.parseMediaType("application/pdf"))
                .body(resource);
    }
}

这是编写代码以生成pdf的类

@Service
public class PdfDemo {

    @Value("${file.download.base}")
    private String DOWNLOAD_FOLDER;

    public static final String DOWNLOAD_PATH = "tmp/downloads/";
    public static final String ZIP_PATH = "/tmp/zip_files";
    public static final String FILE_NAME = "student_list";
    public static final String SERVER_REPORT_URL = "/report/html";
    public static final String DOWNLOAD_FILE_PATH = DOWNLOAD_PATH + FILE_NAME;
    public static final String ZIPFILE = "/tmp/zip_files/cmed_report.zip";
    public static final String ZIPFILE_NAME = "cmed_report.zip";
    public static final String SRCDIR = "/tmp/downloads";
    public static final String DATE_FORMAT_PATTERN = "yyyy-MM-dd-HH";

    public static String getBaseURL() throws MalformedURLException {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder
                .getRequestAttributes()).getRequest();
        String baseUrl = "";
        if (request != null) {
            // handle proxy forward
            String scheme = request.getScheme();
            if (request.getHeader("x-forwarded-proto") != null) {
                scheme = request.getHeader("x-forwarded-proto");
            }

            Integer serverPort = request.getServerPort();
            if ((serverPort == 80) || (serverPort == 443)) {
                // No need to add the server port for standard HTTP and HTTPS ports, the scheme will help determine it.
                baseUrl = String.format("%s://%s%s", scheme, request.getServerName(), request.getContextPath());
            } else {
                baseUrl = String.format("%s://%s:%d%s", scheme, request.getServerName(), serverPort, request.getContextPath());
            }
        }

        return baseUrl;
    }

    public static String generatePdfListForStudents()
    {
        WkHtmlToPdf pdf = new WkHtmlToPdf();


        try {
            pdf.addSources(Source.fromUrl(getServerAbsolutePath(SERVER_REPORT_URL)));

            System.out.println("Server absolute path: " + getServerAbsolutePath(SERVER_REPORT_URL));
            System.out.println(Source.fromUrl(getServerAbsolutePath(SERVER_REPORT_URL)));

        } catch (Exception e) {
            e.printStackTrace();
        }

        String downloadPath = DOWNLOAD_FILE_PATH + ".pdf";

        pdf.addArguments(
                Argument.from(EnableJavascript));

        System.out.println("PDF Location: " + downloadPath);
        // Save the PDF
        File file = new File(downloadPath);
        System.out.println("Directory status: " + file.exists() + " " + file.isDirectory());

        try {
            System.out.println("Paths.get: " + Paths.get(downloadPath));

            pdf.save(Paths.get(downloadPath));
        } catch (IOException e) {
            e.printStackTrace();
        }
        return downloadPath;
    }

    public static String getServerAbsolutePath(String requestPath) throws MalformedURLException {
        String URL = getBaseURL() + requestPath;
        return URL;
    }
}

这是Controller类中SERVER_REPORT_URL的{​​{1}}类

PdfDemo

现在,当我在HTML页面上点击@Controller public class HtmlViewReportController { @Autowired StudentService studentService; @GetMapping(value = "/report/html") public String getPdfReportForStudent(Model model) { model.addAttribute("studentList", studentService.findAll()); return "sample"; } } 时,我得到了Download PDF。错误堆栈跟踪在这里

error

这是github link。如果任何人都可以解决这个问题,将非常有帮助。

2 个答案:

答案 0 :(得分:0)

您是否在计算机中安装了wkhtmltopdf?在enter image description here

上尝试

我使用来自以下位置的Pdf对象以一种更简单的方式进行了操作

import com.github.jhonnymertz.wkhtmltopdf.wrapper.Pdf;

生成pdf看起来更容易,如下所示:

@Override
public String save(String url) throws IOException, InterruptedException{
    Pdf pdf = new Pdf();
    pdf.addPageFromUrl(url);
    return mockSaveS3(pdf);
}

private String mockSaveS3(Pdf pdf) throws IOException, InterruptedException{
    File fileTemp = File.createTempFile("pdf-", "");
    File file = pdf.saveAs("apps/" + fileTemp.getName());
    return file.getAbsolutePath();
}

然后我将Url返回到了我存储在apps/目录中的PDF。

答案 1 :(得分:0)

我解决了这个问题。解决了很长时间。我在媒体上一步一步写了博客。我在这里发布该链接。您可以在此处查看所有步骤。我还提供了示例项目的github链接。看 here