在 JSF 中读取和显示加密的 PDF 文件



根据BalusC的主页 我实现了函数 downloadPDF() ,它从文件系统读取 PDF 文件并将其显示在浏览器中。 此函数按预期工作。

此外,我有一个类EncryptionService,它允许我加密和/或解密给定文件。 这也按预期工作。

不幸的是,似乎无法读取PDF文件,解密并在浏览器中显示它。 它以浏览器尝试一遍又一遍地加载文件而根本不显示任何内容而结束。

下面的代码显示了我对BalusC的PDF处理程序的简单修改。

public void showDocument(String path, boolean decrypt) throws IOException, InvalidKeyException {
    FacesContext facesContext = FacesContext.getCurrentInstance();
    ExternalContext externalContext = facesContext.getExternalContext();
    HttpServletResponse response = (HttpServletResponse) externalContext.getResponse();
    File file = new File(path);
    BufferedInputStream input = null;
    BufferedOutputStream output = null;
    try {
        if(!decrypt)
            input = new BufferedInputStream(new FileInputStream(file), DEFAULT_BUFFER_SIZE);
        else {
            // update MessageDigets, return Key
            cipher.init(Cipher.DECRYPT_MODE, genKey(passphrase));
            input = new BufferedInputStream(new CipherInputStream(new FileInputStream(file), cipher), DEFAULT_BUFFER_SIZE);
        }
        response.reset();
        response.setHeader("Content-Type", "application/pdf");
        response.setHeader("Content-Length", String.valueOf(file.length()));
        response.setHeader("Content-Disposition", "inline; filename="" + path + """);
        output = new BufferedOutputStream(response.getOutputStream(), DEFAULT_BUFFER_SIZE);
        byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
        int length;
        while ((length = input.read(buffer)) > 0) {
            output.write(buffer, 0, length);
        }
        output.flush();
    } finally {
        try {
            input.close();
            output.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    facesContext.responseComplete();
}
发生了什么

就像控制台错误所说的那样

网::ERR_CONTENT_LENGTH_MISMATCH

这表示响应正文中返回的内容的实际大小与响应的 Content-Length 标头中指示的大小不匹配。

为什么会这样

造成差异的原因主要体现在两个因素中:

  • 加密通常会增加加密内容的大小。加密过程需要通过密码对内容进行混淆,这通常意味着扔进会使内容无法使用的东西。另一方面,解密会将内容恢复到原始大小

  • 浏览器容易缓存。如果您提供足够多的不同文件(使用相同的文件名),您的浏览器可能只是确定它是具有相同内容的同一文件,并且只提供文件的缓存版本。在您的情况下,您声明对加密文件的引用,访问该文件,对其进行解密,然后将解密的内容直接写入加密版本的同一文件句柄中。

  • 基于磁盘的 I/O 与 RAM 或 CPU 不是 100% 同步的。写入磁盘和从磁盘读取仍然以 RAM 等待磁盘的形式产生开销。

要修复

  • 为操作中涉及的每个文件生成随机/不同的文件名。这意味着加密内容的单独文件名和解密表单的单独文件名

  • 作为上述观点的推论,将不同的输出流打开到不同的文件,也使用不同的File访问变量。

相关:

  • 支持Bean方法和Primefaces对话框的"oncomplete"属性的意外行为。

相关内容

  • 没有找到相关文章