用PHP和jQuery将PDF打印到页面上

3

我需要帮助写一个PHP脚本,通过PHP脚本在新标签页中加载PDF文件。我这么做是为了确保只有已登录并拥有链接的用户才能访问PDF文件,否则父目录下的.htaccess将阻止访问。
以下代码可以读取PDF文件:

$file = '../path-to-file.pdf';
$filename = 'filename.pdf';
header('Content-type: application/pdf');
header('Content-Disposition: inline; filename="' . $filename . '"');
header('Content-Transfer-Encoding: binary');
header('Accept-Ranges: bytes');
@readfile($file);

这样做的结果被传递到下面展示的一个AJAX函数中,该函数生成一个新的选项卡并将响应放在其中:
$.ajax({
    url: '../includes/function.projects.php?view-media=' + item,
        success: function(data) {
            $(window.open().document.body).html(data);
        }
    })

这一切都很顺利,只有在打开新标签时会出现问题,因为我直接将响应写入文档的HTML中,所以会得到一屏幕像这样的文本:
%PDF-1.5 %���� 2 0 obj << /Linearized 1 /L 17007 /H [ 687 126 ] /O 6 /E 16732 /N 1 /T 16731 >>

所以我的问题很简单; 有人之前试过做到这一点吗?如果是这样,我应该使用哪些库/缺少哪些头文件等等

我已经在这里看到了这个问题,但我无法让人们列出的答案起作用,所以我已经没有想法了。

任何帮助将不胜感激,提前致谢!

3
这只是一个猜测,虽然我已经做过类似的事情来保护图片。我认为你不能仅通过 window.open.document.body 这样简单地传递数据,因为你没有带任何头信息。为什么不直接弹出一个窗口,将你的 function.projects.php?view-media=' + item 作为 URL,并在顶部进行安全检查呢? - dmgig
嗯...看看这个:https://dev59.com/tWkv5IYBdhLWcg3wjxdl - dmgig
这是个好主意!我已经编写了一个检查会话的函数,所以实现起来会很容易。另一种方法是我刚开始研究的,即加载一个预先构建的页面,通过GET变量传递PDF的URL,然后使用JS库获取并将PDF加载到页面上...不过我更喜欢你的想法 :) - lewisnewson
祝你好运!不过请查看另一个链接 - 也许你只需要将其转换为二进制,并在字符串前加上"data:application/pdf;base64,",那么你现有的计划就能够实现。 - dmgig
如果没有人完整地回答您的问题,请回来把您自己的解决方案作为一个答案。我很想看看您是如何解决问题的。 - dmgig
1
好的,伙计,我会继续调试,一旦我有了一个运行顺畅的东西,我就会将其添加为答案。 - lewisnewson
1个回答

3
我有一个解决方案。如果有更好的方法,请告诉我,但目前这个方案非常完美!我发现了一个名为PDFObject的JS库,可以用于在HTML文档中轻松嵌入PDF文件的跨浏览器解决方案。使用这个库,我可以在服务器上传递PDF链接以及要嵌入的目标div(在我的情况下,我已经将它设置在模态框内,这样我们就保持在同一页上)。

因为我们在同一页上,我可以使用之前在项目中编写的函数来阻止访问整个页面,该函数将重定向用户到索引页面,如果他们没有正确的访问级别。以下类似的代码可以实现:
function checkSession() {
    if(empty($_SESSION)) {
        header("Location: /?cheeky_monkey");
    }
}

如果用户试图直接访问PDF文件,htaccess中的此代码会阻止他们这么做。只有在通过应用程序定向访问时才允许访问:
SetEnvIf Referer "localhost" is_local_referer
<FilesMatch "\.pdf$">
    Require env is_local_referer
</FilesMatch>

首先,需要做的就是向脚本标签传递一个URL以在单击PDF时进行加载,可以通过以下代码实现:

  1. 首先我们需要获取PDF的URL(你可能可以跳过此步骤)

首先,每当有人点击查看PDF时,将调用此JavaScript代码(此调用仅嵌套为onclick属性):

function viewMedia(projectID, type, item) {
    $.ajax({
        url: '../includes/function.projects.php?cid=' + projectID + '&type=' + type + '&view-media=' + item,
        success: function(data) {
            $('.pdf-script').html('<script>PDFObject.embed("' + data + '", "#the-pdf");</script>');
            $('#viewMediaModal').modal('toggle');
        }
    })
}

这是在php页面上运行的代码。

public function viewMedia($item) {
    $mediaItems = unserialize($this->media);
    $file = '/path/to/pdf/' . $mediaItems[$item]['file'];
    echo $file;
}

这个函数返回数据的一个例子:
/path/to/pdf/example-pdf.pdf
  1. 使用此方法加载PDF

一旦我们获得了正确的PDF链接并且AJAX返回成功,接收到的数据可以用于重新生成JavaScript代码,这次包括新的PDF链接:

success: function(data) {
    $('.pdf-script').html('<script>PDFObject.embed("' + data + '", "#the-pdf");</script>');
    $('#viewMediaModal').modal('toggle');
}

这是模态框主体结构的样式:
<div class="modal-body">
    <div id="the-pdf"></div>
    <div class="pdf-script" style="display: none;">
        <script>PDFObject.embed('', '#the-pdf');</script>
    </div>
</div>
  1. 结果

上述代码序列的结果会切换出一个模态框,如下所示:

enter image description here

如果用户尝试直接访问文件,则会显示如下界面:

enter image description here


哇,太棒了。谢谢你分享这个。 - dmgig
没问题!:)) - lewisnewson

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接