我正在为某个社交网络创建一个预定帖子的网络服务。
需要帮助处理高流量下的文件上传。
流程概述:
- 用户将文件上传到SomeServer(不是我的)。
- 然后,SomeServer 会使用 JSON 字符串进行响应。
- 我的 Web 应用应存储该 JSON 响应。
选项 1:保存、cURL 开机自检、删除 tmp
我让它工作的愚蠢方式:
- 用户将文件上传到我的网络应用;
- MyWebApp cURL 是指向 SomeServer 的文件,获取响应。
选项 2:JS 魔法
它可能是完美的聪明方式:
- 用户从iFrame中将文件直接上传到SomeServer;
- MyWebApp 通过 JavaScript 获取响应。
但由于"同源政策",这是不可能的,不是吗?
选项3:nginx代理?
生产服务器的更好方法:
- 用户将文件上传到我的网络应用;
- nginx拦截文件上传并将其直接发送到SomeServer;
- JSON响应也被nginx拦截并由MyWebApp处理。
这有什么意义吗,nginx配置是什么,比如说,/fileupload
位置将其代理到SomeServer?
我没有服务器可以用来代替SomeServer来测试我的建议,但无论如何我都会试一试。 如果我错了,那么我想你只需要使用Flash(来自VK的示例代码)。
如何使用 iFrame 将文件上传到 SomeServer,接收 JSON 响应,然后使用 postMessage
将 JSON 响应从 iFrame 从站点传递到主窗口。据我了解,这几乎是最初创造postMessage
的动机。
总的来说,我正在考虑类似这样的东西或 YUI 的 io()
模块,但添加了postMessage
以绕过相同的来源策略。
或者在VK的情况下,使用他们明确的iFrame支持。 在我看来,您可以将一种方法添加到全局 VK 对象,然后使用 VK.callMethod()
从 VK 源域调用该方法。 您可以使用该解决方法创建一个函数,该函数可以从隐藏的 iFrame 读取响应。
因此,您使用VK.api('photos.getUploadServer', ...)来获取POST URL。
然后,使用 JS 插入该 URL 作为用于上传文件的表单的操作。 按照io()
文档和complete
函数中"以 HTML 表单上传文件"下的示例,使用 postMessage
将 JSON 发布回父窗口。请参阅此处的示例和文档。 (如果它不适用于io()
,如果我对VK.callMethod()
是正确的,您当然可以使用自己的示例代码使其工作。
然后,为了响应postMessage
,您可以使用常规 AJAX 将 JSON 响应上传回服务器。
我只能看到解决这个问题的两种主要方法:服务器端代理和javascript/客户端跨站点上传。你的方法1
和3
是一回事。使用cURL还是nginx发布文件并不重要 - 无论如何,性能方面都无关紧要。因此,如果您已经从您的问题中实现了方法1
,我认为没有任何理由切换到3
.
关于javascript和同源策略,似乎有很多方法可以实现你的目标,但在所有这些方面,要么你的方案必须得到SomeServer开发人员的支持,要么你必须有某种访问SomeServer的权限。以下是可能性的大致列表:
- CORS - 必须允许您的域访问 SomeServer 的域;
- 更改 document.domain - 这要求您的网页和目标网页托管在同一网域的子网域中;
- 使用 Flash 上传器(例如 SWFUpload)——仍然需要通过跨域策略(如果是 Flash)在 SomeServer 域的根目录中通过跨域.xml允许您的域;
- xdcomm(例如 EasyXDM)- 要求您至少可以将 html 页面上传到目标域。然后,此页面可以用作JavaScript代理,用于使用SomeServer的iframe进行操作。
实际上,最后一个对您来说可能是一个真正的可能性,因为您可以将文件上传到SomeServer。但是,当然,这取决于它的实现方式 - 例如,如果文件来自另一个域,或者如果有一些安全措施不允许您托管html文件,则可能无法成功。