客户端上传文件到远程服务器的最佳方法?

Lio*_*ing 8 php file-upload remote-server

我有两台服务器.第一个(Main)是安装了脚本和数据库的服务器.
第二个(远程)是仅上载文件的服务器(仅用于存储).

现在我对如何上传文件感到困惑,我有两个想法,我不知道它们是否是最好的方法.

想法:

  1. 首先通过ajax将文件上传到主服务器,然后进行所有安全操作(检查大小,类型等),然后再次上传到第二台服务器(远程服务器).

  2. 通过ajax将文件直接上传到第二个(远程服务器),并在那里进行所有检查和安全操作,然后将文件信息发送到第一个服务器(main),将文件信息存储到数据库中(不推荐).

我想知道大型上传网站在存储用户上传的文件时的行为,他们如何将文件上传到远程服务器?

PSW*_*Wai 2

两种机制都是有效的。事实上,我们在两款产品中尝试了这两种方法。他们每个人都有自己的优点和缺点。

假设:主服务器为 Web UI 提供服务。让我们将两台服务器命名为main.comremote.com

您需要考虑的主要因素是:

  1. 跨源资源共享(CORS:检查这是否是一个大问题的最直接方法是您是否需要支持 IE <= 9。旧版 IE 不支持 XHR2,因此无法进行 AJAX 文件上传。有一些流行的后备方案(例如 iframe 传输),但每种方案都有自己的问题。

  2. 带宽main.com:如果文件先上传至remote.com,则所需带宽加倍。根据您的服务器是否位于负载均衡器后面,要求会有所不同。直接上传可remote.com有效利用带宽。

  3. API响应时间:除非你的API正在做乐观更新,否则它需要等到文件完全重新上传才能remote.com可靠地响应。此外,这取决于main.com和之间的 RTT remote.com

  4. API 域的数量:这是一个小问题。Web 客户端必须指定哪个域用于哪个 API。然而它确实与上面的 CORS 问题有关。

  5. 性能:如果 Web 服务器正在处理文件上传,则当服务器处理大文件(或大量文件)时,可能会出现性能问题。它可能会影响其他用户。

机制

1.客户端上传到main.com. main.com重新上传到remote.com

  • CORS:没问题
  • 带宽:双倍
  • 响应时间:双倍(往返);正常(乐观)
  • API域:1个
  • 性能:可能会影响 Web 服务

2.客户端上传到remote.com. remote.com发送信息至main.com

  • CORS:有问题
  • 带宽:高效
  • 响应时间:高效
  • API域:两个
  • 性能:没问题

3. [额外] 客户端上传到main.com. main.com将文件流式传输到remote.com. remote.com发回文件信息。

  • CORS:没问题
  • 带宽:双倍
  • 响应时间:小于两倍(流式传输)
  • API域:1个
  • 性能:比方法 1 更好,因为它具有更好的内存占用

结论

根据您的用例,您需要使用不同的机制。对于我们的案例,我们对旧产品使用方法 2(直接上传),因为我们需要支持旧浏览器(IE 7、FF 3)。在许多不同的情况下,跨域问题一直困扰着我们(例如,当客户使用代理时等)。

我们的新产品使用方法 1。正常情况下,带宽和响应时间问题还算可以,但当 Web 服务器和远程服务器跨大陆部署时,性能就较差了。我们做了很多优化使其可以接受,但仍然比方法 2 差。

方法3是我自己在一个业余项目中使用的。将其包含在这里是因为我认为它也是一个很好的候选者。

编辑

流式传输(方法3)和重新上传(方法1)的区别主要在于文件的存储方式main.com。这会影响资源分配。

重新上传时,上传的2GB文件首先存储在 中main.com,然后重新上传到 中remote.commain.com必须分配资源来临时存储文件(磁盘空间、内存、用于IO的CPU)。此外,作为一个串行过程,完成上传到 所需的总时间remote.com加倍(假设上传到 的时间main.com等于上传到 的时间remote.com)。

对于流式传输,正在上传的文件main.com会同时上传到remote.com. 由于main.com接收到文件块remote.com后立即上传该块,因此上传过程是重叠的,从而导致上传时间更短(小于两倍)。换句话说,如果 处不需要处理main.commain.com则 是 的有效代理remote.com。此外,由于文件不是作为一个整体存储的main.com(块通常存储在内存中),因此它不会比重新上传消耗那么多资源。然而,如果main.com需要将文件作为一个整体进行处理,那么流式传输并不能带来太大的好处。