【问题标题】:Generating PDF between 2 sites在 2 个站点之间生成 PDF
【发布时间】:2012-11-16 08:48:47
【问题描述】:

我正站在一个充满解决问题的潜在方法的十字路口。我的问题是我想将特定用户推荐给为他们呈现相关 PDF 文件的独特页面。最好,我想将它们引至一个站点,该站点没有相关的 MySQL 数据和用于 pdf 渲染的插件。希望您能阐明我应该使用哪种解决方案。

参考

  • 站点 A - 我更愿意推荐他们访问的站点
  • 站点 B - 包含 MySQL 数据和 PDF 插件的站点

信息

  • 这两个网站都是通过 CakePHP 1.3 构建的
  • 站点 A 当前没有附加数据库。它仅在对站点 B 的 API 调用上运行。
  • 这些 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 到站点 B 运行 API,以根据来自 url 的 ID 获取相关数据。但也有站点 A 上的 PDF 插件。

优点:从某种意义上说,这是一种非常合乎逻辑的方法。
缺点:我宁愿只在站点 B 上生成所有 PDF。更容易管理所有这些。
虽然:我有点不确定与解决方案 2 相比,这种方法有多少(如果有的话)好处。

非常感谢您的宝贵时间。请激发一个给定的解决方案,或提出您自己的解决方案。

编辑:虽然代码示例总是受到赞赏,但我更感兴趣的是为什么应该使用其中一个或另一个解决方案的共鸣和逻辑。我已经知道如何通过编码解决大多数这些解决方案。对于访问者,请随时链接到有关您的回复的相关功能和方法。

【问题讨论】:

    标签: php cakephp pdf cross-domain


    【解决方案1】:

    您似乎想从公众视线中隐藏站点 B。

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

    编辑:

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

    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 的一部分,否则将无法访问。

    通过启用 proxy_mod 并在 VHOST 或服务器配置下设置 ProxyPass 和 ProxyReversePass,将修改的文件是 siteA.com 主机的 Apache 配置。

    【讨论】:

    • 这种方法是否需要两个站点共享服务器?我的第一个方法是通过 VirtualHost 运行它,但这将强制这两个共享服务器的需要。
    • 从外观上看,这个解决方案似乎更适合我。我想这比通过 cURL 简单地“翻录”生成的 pdf 更好吗?但是,我仍然没有完全掌握 Apache。如果我希望 pdf.site-a.com 加载 site-b.com,或者如果 cakePHP 可以处理 uri,甚至 site-b.com/pdf/pdf_generators,您能否提供一个我应该修改哪些文件的示例?
    • 更新了答案中的描述
    • 我最终使用了虚拟主机和重写器。干杯!
    【解决方案2】:

    您始终可以在站点 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下载文件.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 相当。我当前的 pdf 插件以某种方式生成它,使浏览器能够在可能的情况下现场显示它,否则下载它。保留该功能会很好,但我不确定插件发送什么标头。也许是您在示例中提供的那个?
    • 确实是您的解决方案 2。您不需要标题的精确副本。如果您将内容类型设置为 PDF,这就是浏览器所期望的。添加内容配置将使现场或下载弹出窗口成为可能。内容长度标头很有用,因此浏览器知道何时完成下载并可以显示下载仪表。
    【解决方案3】:

    有趣的问题。从所有不同的解决方案中,我假设您在可以做的事情上非常灵活。

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

    您可以使用 Gearman 与 PHP 交互来创建作业队列。

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

    优点

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

    缺点

    • 需要安装和设置 gearman
    • 需要您创建 gearman PHP 脚本才能实际生成 PDF

    我选择这条路线的主要原因是用户体验、易于扩展和对工作进程的控制。

    旁注

    您对站点 A 和 B 的设置似乎有点奇怪,但我相信您有您的理由。如果您有两台服务器,最好使用站点 A 上的 nginx 将所有请求代理到内部服务器 B,并在其上安装 Apache、DB 和 gearman。然后,随着网站流量的增长,您可以将应用程序分离到不同的服务器。

    【讨论】:

    • 网站的设置是我留下的,而不是我个人的喜好。所以基本上,您说我应该将 PDF 作为附件发送到他们的邮件中?虽然这是一个不错的方法,而且我可以通过 CodeIgniter 轻松完成,但我不确定我是否可以轻松地创建 PDF 文件并将它们附加到 CakePHP 1.3 中的相同脚本执行中。我可能也希望能够停用这些 PDF。 (我知道人们可以拯救他们,但很少有人会)
    • 您不必以电子邮件的形式发送。您可以将它们发送到显示“已创建 PDF,页面将在 10 秒内自动刷新”的页面,并在生成 PDF 后停止刷新。发送电子邮件只是一个建议 - gearman 只是一个工作队列,工作完成后如何将 PDF 发送给用户取决于您;)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-11-16
    • 1970-01-01
    • 1970-01-01
    • 2023-03-24
    • 1970-01-01
    • 1970-01-01
    • 2017-01-10
    相关资源
    最近更新 更多