在2个站点之间生成PDF

时间:2012-11-28 13:25:54

标签: php cakephp pdf cross-domain

我站在十字路口的前方,充满了解决问题的潜在方法。我的问题是我想将特定用户引用到为他们呈现相关PDF文件的唯一页面。最好,我想将它们引用到一个站点,相关的MySQL数据和pdf渲染插件没有打开。希望您可以了解我应该使用哪种解决方案。

参考

  • 网站A - 我希望将网站推荐为
  • 的网站
  • 网站B - 包含MySQL数据和PDF插件的网站

信息

  • 这两个站点都是通过CakePHP 1.3
  • 构建的
  • 网站A目前没有附加数据库。它只在API调用上运行,只能运行到站点B.
  • 这些PDF文件的生成量不会太大,但找到一个也能解决这个问题的解决方案会很有意思
  • 这些PDF的引用发生在事件中,不会同时发送给数千名用户。

解决方案#1

将它们引用到站点B并在那里生成所有内容。

优点:易于修复。
缺点:我不希望这些用户知道站点B.站点B主要用于内部通信,对于给定的用户,最好不要这样做。
虽然:相反,请避免使用此功能。

解决方案#2

在网站A上有一页cURLs页面等于解决方案#1,然后输出相同的结果。

优点:相当容易修复。
缺点:想不出来。
虽然:浏览器会明白我输出PDF吗?或者我(如果可能)复制标题回复来自cURL请求并在输出之前将它们设置在自己的header()中?

解决方案#3

在站点B中生成一次PDF并将其放在站点A上。然后只需参考.pdf链接。

优点:加载速度更快。在这种情况下并不重要,甚至可能不被注意 缺点:无法轻松修改PDF输出 虽然:我如何转移文件?这两个站点位于同一台服务器上,因此可以通过简单的路径更改,但站点之间的所有其他通信都是由于它们不需要共享服务器。羞于打破这种设计。也许我必须做一个高级的cURL请求并将pdf文件作为POST从站点B发送到站点A并上传它?但是,这似乎也不是一个整洁的解决方案。

解决方案#4

从站点A运行API到站点B,以根据来自URL的ID获取相关数据。但也有网站A上的PDF插件。

优点:在某种程度上,这是一种非常合乎逻辑的方法 缺点:我希望仅在网站B上生成所有PDF。使管理所有这些变得更容易 虽然:我有点不确定这种方法与解决方案2相比有多大(如果有的话)更有益。

非常感谢你的时间。请激励给定解决方案之一,或展示自己的解决方案。

编辑:虽然代码示例总是受到赞赏,但我更加关注应该使用哪种解决方案或其他解决方案的共鸣和逻辑。我已经知道如何通过编码解决大部分这些解决方案。对于访问者,请随时链接到有关您的回复的相关功能和方法。

3 个答案:

答案 0 :(得分:1)

看起来你想隐藏网站B的公众视线。

最简单的方法是在站点A和站点B之间创建反向代理。 您可以执行类似sitea.com/pdf-items/的任务,将提供siteb.com/

编辑:

反向代理可以是跨域的,服务器不必共享任何共同点,除了站点B可被站点A访问(听起来已经是这样)

Apache使用mod_proxy(http://httpd.apache.org/docs/2.2/mod/mod_proxy.html

的方法很简单

快速谷歌推出了一个指南,用于在Apache上进行设置。 http://www.apachetutor.org/admin/reverseproxies

Nginx也有 http://www.cyberciti.biz/tips/using-nginx-as-reverse-proxy.html

IIS有点复杂,我从来没有设置它,但根据文档确实存在这种能力。

编辑2:接近

这里我们不必担心PHP组件。发生的事情是Apache服务器将根据指定的代理映射转发请求,例如如果代理设置为Sitea.com/pdf siteb.com/,则sitea.com/pdf/alpha.pdf将实际请求siteb.com/alpha.pdf。在这个模式中,它将忽略sitea.com PHP路由,但它将尊重siteb.com路由,因为它是一个完整的请求,但由sitea的网络服务器完成。

关于尊重siteb的请求,这意味着sitea.com/pdf/getpdf.php?id=1实际上将通过sitea.com/getpdf.php?id=1进行所有动议。

或者,如果您想在siteA.com上设置VHOST,例如pdf.sitea.com,您可以设置pdf.sitea.com映射到siteb.com的代理,但如果sitea和siteb都是公开访问。

如果您的受众可以使用sitea.com并且siteB位于具有受限访问权限的防火墙后面,则反向代理最有效,因此代理将让sitea.com访问siteb.com的一部分,否则该部分将无法访问。

要修改的文件是siteA.com主机的Apache配置,方法是启用proxy_mod并在VHOST或Server配置下设置ProxyPass和ProxyReversePass。

答案 1 :(得分:0)

您始终可以在站点B上创建“隐藏”或至少未知页面,生成PDF并直接输出(无需下载对话框)。然后在网站A上你可以直接破坏网站B的链接,从网站B下载内容,并将其显示给用户。

用户不知道站点B存在,但它会慢一些,因为两台服务器之间的数据流量会更多。

现场B hiddenfile.php:

<?
$p = new PDFlib();
if ($p->begin_document("", "") == 0) {
    die("Error: " . $p->get_errmsg());
}
$p->set_info("Creator", "Hugo Delsing");
$p->set_info("Author", "Hugo Delsing");
$p->set_info("Title", 'Hi');

$p->begin_page_ext($docWidth, $docHeight, "");

$p->end_page_ext("");
$p->end_document("");

$buf = $p->get_buffer();

$len = strlen($buf);
header("Content-type: application/pdf");
header("Content-Length: $len");
header("Content-Disposition: inline; filename=hello.pdf");
print $buf;
exit;
?>

和网站A downloadFile.php

<?
$content = implode('', file('siteb/hiddenfile.php?user=1'));
$len = strlen($content );
header('Content-type: application/pdf');
header("Content-Length: $len");
header('Content-Disposition: attachment; filename="downloaded.pdf"');
print $content;
exit;
?>

所以我想我会以不同的方式使用解决方案B,以保持单独的服务器选项。为什么?所有解决方案都很好,但这一次对你没有任何利弊。所以我猜你回答了自己的问题。

答案 2 :(得分:0)

有趣的问题。从所有不同的解决方案中,我认为你可以做的很灵活。

我个人会将站点B用作其上有数据库的作业队列服务器(尽管在不同的服务器上数据库也会更好)。询问用户的电子邮件地址,一旦完成工作(处理PDF),他们就会通过电子邮件发送给他们,或者你可以按照我在评论中建议的那样做,并将它们发送到一个页面,说“生成pdf,将刷新10秒“一直保持刷新,直到找到生成的PDF。这样也可以很好地扩展(只需添加更多工作者),并且在生成PDF时不会阻止用户。

您可以使用Gearman与PHP连接以创建作业队列。

http://php.net/manual/en/book.gearman.php

<强>赞成

  • 可以很好地扩展 - 如果您需要一次生成更多PDF,只需添加更多工作人员
  • 生成PDF时,如果认为页面已崩溃,则不会停止使用
  • 不仅限于PDF,您可以在其中排队任何CPU密集型作业
  • 不需要随着网站流量的增加而被扯掉并替换为不同的东西(只需添加更多工作人员)
  • 允许控制尝试生成PDF的进程/线程数量(例如,apache允许一次生成10个或更多PDF文件 - 直接在Web请求过程中完成后,您几乎无法控制它攻击者使您的网站崩溃的方法)

<强>缺点

  • 需要安装和设置gearman
  • 要求您创建齿轮手工PHP脚本以实际生成PDF

我沿着这条路走下去的主要原因是因为用户体验,易于扩展性以及对工作流程的控制。

旁注

您对网站A和B的设置似乎有点奇怪,但我确定您有理由。如果您有两台服务器,那么您最好使用站点A上的nginx代理对内部服务器B的所有请求,其中包含Apache,DB和gearman。然后,随着网站流量的增长,您可以将应用程序分离到单独的服务器上。