iframe 无刷新文件上传
最近写的一个小站,搭建在 SAE 上的一个私有相册类应用,带简单的用户管理和权限控制。在写后台图片上传的时候遇到一点小问题。因为是搭建在 SAE 上又不想开启 Storage 服务,所以图片存储就只能找第三方的服务。正好发现七牛云存储有免费套餐,而且支持很多常用的图片操作(比如缩略图可以不用自己手动裁了),就打算集成到这边来。以下所说的是上传图片到七牛云存储的私有空间中的一种方法。
根据七牛官方的文档,只要有根据不同上传策略(个人理解就是一些参数设置的集合)生成的 token ,上传文件到私有空间中是很容易的一件事,但实际就是卡在跨域这个问题上。我自己的网站 A 和七牛上传网站 B 无法用 Ajax 上传,于是我就想到用 iframe
。
用 iframe
的话也是有跨域的限制。大致的方法是这样的:在文件表单那里设置 target
指向一个 iframe
(使表单 target
属性和 iframe
的 name
属性一致),这样表单提交的时候,刷新(产生页面跳转)的就是那个 iframe
的 contentDocument
,不会影响到父框架的交互体验。而通过服务器返回一段 script
内容,就可以对表单提交的结果进行一些处理,比如提示上传是否成功之类的。
同域下基本这个方法就够用了,表单提交到自己服务器上,返回一段 script
,调用父框架的函数来处理上传结果。但跨域的话就很麻烦,因为浏览器它不让你两个域的内容产生交互。
我想来想去,最后还是用了代理的方法。之前在我的博客文章《中国天气网 API 》的评论中我有提到使用服务器端代理的方式来使用 Ajax 传送数据的方法。这个方法确实很好用,缺点就是麻烦,因为需要服务器端的支持,但是麻烦总比没用好。
所以最后实现的方法就是在服务器端加上一个图片上传之后的回调处理。在上传表单所在的页面载入之前,构造上传策略的时候,使用七牛 SDK (我使用的是 Python SDK )设置 returnUrl
和 returnBody ,这样在表单提交、文件上传之后,七牛会把你在 returnBody
中指定的数据 POST 到 returnUrl
去。在 returnUrl
的对应处理函数里,你就可以把返回的数据加工一下,拼接一段 script
响应给 iframe
,从而避免跨域的问题。