收到标题后立即触发下载对话框

时间:2017-11-23 11:28:33

标签: php http internet-explorer firefox download

我有PDF导出需要一段时间来创建PDF。我希望用户能够单击导出链接并立即显示下载对话框。这样他们就可以开始下载并等待它完成。而不是单击链接,等待生成,然后再次等待下载。

这是PHP中一个非常简单的例子:

<?php

header('Content-Type: application/pdf');
header('Content-Disposition: attachment; filename=test.pdf');
flush();

// time consuming PDF creation happens here
sleep(15);
echo 'pdf contents would be here';

我们的想法是将相应的标题,flush()发送到浏览器,慢慢创建PDF并最终将其发送到浏览器。

这在chrome中非常有效。下载对话框会立即弹出,睡眠是下载等待时间的一部分。

在Firefox和InternetExplorer中,这不起作用。这些浏览器在显示下载对话框之前等待整整15秒。

任何想法如何使下载对话框立即弹出将不胜感激。

2 个答案:

答案 0 :(得分:2)

某些浏览器会在显示下载对话框之前等待实际内容。 因此,解决方案很简单:在创建PDF内容之前发送一些PDF内容。

等一下。 在你拥有之前你怎么发送东西? 这听起来像需要时间机器,对吗? 别担心,有办法绕过它。

PDF content starts with %PDF,因此您只需在调用flush()之前发送%PDF。 PDF创建完成后,在回显之前删除新创建的PDF内容的前4个字节。

<?php
// disable output buffering
while (@ob_end_clean());

header('Content-Type: application/pdf');
header('Content-Disposition: attachment; filename=test.pdf');

// send some content to trigger the download dialog
echo '%PDF';
flush();

// time consuming PDF creation happens here
sleep(15);
$pdfContent = '%PDF-pdf contents would be here';
echo substr($pdfContent, 4);

此解决方案适用于任何语言,因为它不依赖于任何仅限PHP的功能。

如果你想做绝对最小值,你也可以发送1个字节%,然后在回显之前只删除第一个字节。 结果相同。

答案 1 :(得分:0)

这是一般性问题,与任何特定语言无关。 我们正在制作一个过程,等待一段时间,直到PDF生成,然后开始我们的下载过程。

因此,为了等待PDF生成,我们将使用sleep()函数来允许进程等待指定的时间段 - 如上所述。

sleep(15)

现在,我们无法flush()在向浏览器生成pdf之前的空内容。所以我们可以在开始之前发送一些静态内容并开始我们的刷新过程。

成功完成PDF生成后,我们可以删除之前添加的内容,并将更新的内容回显给浏览器的flush()函数。

所以总体代码是,

<?php

// Initialize the Basic Header

ob_start(); // Start Buffering
header('Content-Type: application/pdf');
header('Content-Disposition: attachment; filename=test.pdf');

// Adding content before the PDF Generation Process
echo 'demo';

// Flushing content to the Browser

ob_end_flush();
ob_flush(); 
flush();

// time consuming PDF creation happens here
sleep(15);

$Content = 'demoother pdf content';

// Removind the Added Content
echo substr($Content, 4);

?>