从浏览器上传文件到另一个域的最佳方法是什么?

时间:2012-04-10 07:57:43

标签: file-upload nginx cross-domain same-origin-policy vk

我正在为某些社交网络创建预定帖子的网络服务。
需要帮助处理高流量的文件上传。

流程概述:

  • 用户将文件上传到SomeServer(不是我的)。
  • SomeServer然后以JSON字符串响应。
  • 我的网络应用应存储该JSON响应。

选项1:保存,cURL POST,删除tmp
愚蠢方式让我发挥作用:

  1. 用户将文件上传到MyWebApp;
  2. MyWebApp cURL是SomeServer的文件,获得响应。
  3. 选项2:JS魔法
    它可以是完美的聪明方式:

    1. 用户从iFrame中直接将文件上传到SomeServer;
    2. MyWebApp通过JavaScript获取响应。
    3. 但由于“同源政策”,这是不可能的,不是吗?

      选项3:nginx代理?
      生产服务器的更好方法:

      1. 用户将文件上传到MyWebApp;
      2. nginx拦截文件上传并将它们直接发送到SomeServer;
      3. JSON响应也被nginx拦截并由MyWebApp处理。
      4. 这是否有意义,以及将/fileupload位置代理到SomeServer的nginx配置是什么?

2 个答案:

答案 0 :(得分:1)

我只能看到解决此问题的两种主要方法:服务器端代理和javascript /客户端跨站点上传。您的方法13是相同的。无论你是使用cURL还是nginx来发布文件都不应该真正重要 - 无论如何都不是性能方面的。因此,如果您已经从问题中实施了方法1,我认为没有任何理由可以切换到3

关于javascript和同源策略,似乎有很多方法可以实现您的目标,但是在所有这些方面,要么您的方案必须得到SomeServer的开发人员的支持,要么您必须具有某种访问权限。 SomeServer。以下是可能性的近似列表:

  • CORS - 必须允许您的域名访问SomeServer的域名;
  • Changing document.domain - 这要求您的网页和目标网页托管在同一个域的子域中;
  • 使用Flash上​​传程序(例如SWFUpload) - 仍然需要通过跨域策略允许您的域,如果是Flash,则通过SomeServer域的根目录中的crossdomain.xml;
  • xdcomm(例如EasyXDM) - 要求您至少可以将html网页上传到目标域。然后,此页面可用作使用SomeServer的iframe进行操作的JavaScript代理。

实际上,最后一个可能是您的真正可能性,因为您可以将文件上传到SomeServer。但当然,这取决于它是如何实现的 - 例如,如果有另一个域提供文件,或者如果有一些安全措施不允许你托管html文件,它可能无法解决。

答案 1 :(得分:1)

我没有服务器可以代替SomeServer来测试我的建议,但无论如何我都会试一试。如果我错了,那么我想你只需要use Flash (sample code from VK)

如何使用iFrame将文件上传到 SomeServer ,接收JSON响应,然后使用postMessage将iSON的JSON响应从您的网站传递到主窗口。据我了解,这几乎是创建postMessage的动机。

总体而言,我正在考虑like thisYUI's io() module,但添加了postMessage以解决相同的原始政策。

或者在VK的情况下,using their explicit iFrame support。在我看来,您可以向全局VK对象添加方法,然后使用VK.callMethod()从VK原始域调用该方法。您可以使用该变通方法创建一个可以从隐藏的iFrame中读取响应的函数。

因此,您使用VK.api('photos.getUploadServer',...)来获取POST URL。

然后使用JS将该URL作为用于上传文件的FORM的操作插入。按照io() docscomplete函数中“在HTML表单中上传文件”下的示例,使用postMessage将JSON发布回父窗口。见example and docs here。 (如果它不适用于io(),如果我对VK.callMethod()的说法正确,您当然可以使用roll-your-own示例代码。)

然后,为响应postMessage,您可以使用常规AJAX将JSON响应上传回服务器。