php应用程序中的关键代码部分?

时间:2011-04-03 11:10:36

标签: php api rest file-upload

好的,在我看来这有点复杂,我希望我能解释一下。如果有什么不清楚请评论,所以我可以改进这个问题。

我想将用户文件上传到第三台服务器。

所以我们有

  • 用户
  • 网站(运行网站的服务器)
  • 存储服务器(收到文件)

流程应该是:

  1. 网站从存储云网关请求上传网址,该网址直接指向最终存储服务器(类似http://serverXY.mystorage.com/upload.php)。除了请求之外,还会发送“目标路径”(特定于网站和全球唯一)以及重定向网址。

  2. 网站生成一个上传表单,其中存储服务器上传网址为目标,用户选择文件并单击提交按钮。存储服务器处理发布请求,将文件保存到临时位置('/tmp-directory/'.sha1(target-path-fromabove))并将其重定向回网站指定的重定向网址。 “目标路径”也已通过。

  3. 如果用户取消进程或连接中断或其他什么,我不希望保留任何“幻影文件”!此外,必须避免网站数据库中未在存储云中正确处理然后被破坏的条目。这就是这个和下一步的原因

  4. 这些是关键步骤

    • 网站现在将en条目写入其自己的数据库,并向存储api发出一个宁静的请求(已签名,网站必须使用密钥令牌进行身份验证)
    • 将文件从存储服务器上的临时位置复制到最终位置(这应该很快,因为它只是重命名)
    • 相同的休息请求还会在存储网络数据库中插入数据库行以及网站ID作为所有者
  5. 存储服务器上tmp目录中超过24小时的所有文件都会自动删除。

  6. 如果用户关闭浏览器窗口或连接中断,服务器上的程序流也会中止,对吧? 只执行析构函数和注册的关闭函数,对吗?

    我可以以某种方式使这个代码部分“关键”,以便服务器,如果它一旦进入此代码部分,执行它到最后,无论用户是否中止页面加载?

    (当然我知道服务器崩溃或错误可能随时中断,但我现在关注的是常规流程)

    我的其中一个是在网站数据库中有一个标记和时间戳,将文件标记为“已完成”,并在cronjob中检查旧的未完成文件并将其从存储云中删除,然后从网站数据库中删除,但是我真的想避免这个额外的领域和程序。

    我希望存储api非常通用,并在未来的许多其他项目中使用它。

    我看了开发人员和亚马逊s3的谷歌存储。

    他们有同样的问题甚至更糟。在亚马逊S3,您可以“签署”您的发布请求。因此,用户在您的权限下上传文件并直接保存和存储,您必须付费。 如果连接中断并且用户永远不会回到您的网站,您甚至都不知道。 因此,您必须存储您签名的所有上传网址,并在cronjob中检查它们,并删除所有未“到达目的地”的内容。

    针对该问题的任何想法或最佳做法?

2 个答案:

答案 0 :(得分:1)

如果我正确读取此内容,您将在存储服务将用户重定向回您的网站时调用的脚本中执行关键操作。

我看到两个选项可以确保完整地执行关键步骤:

  1. 确保PHP忽略连接状态,并使用ignore_user_abort()运行脚本直至完成。
  2. 触发一些后端进程,该进程与面向用户的脚本分开执行关键操作。这可能就像将作业放入at队列一样简单,如果您使用* NIX服务器(man at获取更多详细信息),或者像拥有专用队列管理守护程序一样复杂,就像一个LrdCasimir建议。
  3. 我遇到过的这类问题都有与其操作相关的非常耗时的过程,因此我总是使用选项2来提供对浏览器的快速响应,并释放Web服务器。选项1易于实现,但选项2最终更容错,因为更新将保留在队列中,直到它们可以成功传送到存储服务器。

    PHP手册中的connection handling页面提供了很多关于HTTP连接期间发生的事情的好的见解。

答案 1 :(得分:0)

我不确定我会称之为“最佳做法”,而是针对此类问题采取一般方法的一些想法。当然其中一个是允许对存储服务器的REST请求的事务异步发生,可以通过监听传入请求的守护进程(通过观察文件的更改,或者套接字,共享内存,数据库,无论你是什么)认为最适合您所在环境中的IPC)或者是一个非常频繁运行的cron作业,可以接收并传送文件。这样做的好处是,您可以向上传文件的用户发送快速消息,而后台进程可以尝试,如果REST服务存在连接问题,请再试一次。您甚至可以进行一些AJAX轮询,以便用户在完成REST过程时可以显示一条漂亮的JS消息。