使用Canvas和File API在单页面应用程序中通过URL上传图像

时间:2014-12-17 13:15:29

标签: javascript canvas ember.js amazon-s3 fileapi

我们有一个单页面应用程序(Rails后端,Ember.js前端),我们正在从服务器端图像上传器转移到客户端图像上传器。我们以前使用Carrierwave gem来调整大小并在服务器上发送到S3。现在我们想要调整大小(使用HTML5 Canvas和File API)并直接在客户端上发送到S3。

当用户从他的计算机中选择图像时,这很有效。它对用户来说肯定更快,并且减少了服务器的负担。

但是,我们的用户已经习惯了"通过网址上传"我们提供的功能。它就像"按图搜索" Google图片搜索功能。用户不是从他的计算机中选择文件,而是将URL粘贴到图像上。

由于同源策略,我们无法在外部图像上使用Canvas API(它会受到污染,请参阅https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial/Using_images#Using_images_from_other_domains)。

我看到两种可能的解决方案:

  1. 为了能够直接从客户端上传到S3,我们需要在服务器上生成预签名密钥。我们可以将URL传递给同一请求中的图像,在生成预签名密钥时将其下载到服务器上,并将图像作为base64有效负载放在响应中。
  2. 在我们的域上使用代理并使用它来绕过SOP。因此,请访问客户端上的图片https://www.mydomain.com/?link=http://www.link.to/image/selected/by/user.jpg
  3. 我的问题是:

    1. 您是否知道绕过同源政策以提供"通过网址上传的其他方式"功能?
    2. 您认为哪种解决方案最好?
    3. 设置2)有多难?我没有设置代理的经验。 FWIW,我们在Heroku上托管我们的应用程序。
    4. 我希望我所描述的情况足够清楚。

      谢谢!

      约伦

1 个答案:

答案 0 :(得分:1)

  1. 是的,您可以强制您的客户将其他域图像下载到本地驱动器,然后从本地驱动器上传该副本。

  2. “最佳”是主观的&相对于您的配置。传统的解决方法是您的选项#2 - 从您的服务器反弹图像。实际上,您所做的只是让您的服务器上传图像并将其重新提供给客户端。如果你期望大量的图像,那么强迫客户下载他们自己的图像可能会更好,而不是通过“清理”他们的图像来搞砸你的服务器。

  3. 设置有多难?这很简单......毕竟你只需要一些服务器代码拉一个远程镜像并将其保存到指定的服务器目录。唯一不起眼的部分是:

    • 确保服务器永远不会将其中一个受客户端启发的URL解释为可执行文件(病毒!)

    • 经常清除新目录,以便服务器不会因为为客户端加载的图像而过度加权

    • 设置客户端可以上传到服务器的图像大小和数量限制(拒绝服务攻击!)。