Flask: 跨域上传的回调方案
为什么80%的码农都做不了架构师?>>>
随着互联网业务的规模不断扩大,网站的开发方式也产生发巨大的变化。就拿上传来说,早些年通常都是网站自身包含上传模块,通过跳转方式或iframe方式进行上传。这没有涉及到跨域,所以对于上传结果的通知是很容易做到的。然而现在越来越多的做法是将上传功能分离开来,形成独立的上传域来提供上传服务。本文主要是针对跨域上传的上传结果通知分析并提供解决方案。
跨域上传的方式
使用第三方存储,如七牛云存储
重定向上传方式
iframe上传方式
使用第三方存储
比如使用七牛云存储,这种方式第三方一般会提供各个语言的SDK,如果正巧您所使用的语言没有相应的SDK,那就只能自己去实现了。实现起来倒也不难,无非就是实现第三方授权的流程,然后通过文件上传协议提交文件到第三方。这种方式一般是通过服务器端来完成的,上传完成后第三方会有个上传反馈,然后返回到前端。
重定向上传方式
这是最传统的上传方式。各种上传方案都可以很容易的实现它。将上传表单重定向到上传网址,完成上传后可携带参数跳转回来。
iframe上传方式
这种方式是在页面中嵌入一个隐藏的iframe,上传表单提交到iframe来完成上传。现代浏览器都比较好的支持了iframe,所以这个方式也是通用的。这也是本文将讨论的上传方案。
iframe上传完成如何通知
同域或子域方式
如果是同域方式,因为iframe是嵌入在网页中,所以可以在iframe上传完成后通过parent来调用父框架提供的方法并将参数传入来实现通知,或者可以在上传完成后父框架获取iframe的引用并得到iframe的输出内容来实现通知。而如果是子域的方式,则还需要设置document.domain为子域。
跨域方式
因为是跨域方式,这将导致上传完成后目标iframe没有权限去调用父框架中的方法,并且父框架也没有权限去访问子框架的内容,所以无法进行通知上传结果。
是的,一般来说,在iframe上传完成后都会输出数据或一段js代码。但是如果输出的是一个iframe呢?本文将用2个host来演示这种情况。www.aw.com 是需要上传的网站,www.file.com 是提供上传的网站。我们来看个图:
上图很清晰的体现了这种包含关系。A上传到B,B上传完成后输出iframe,并指向A域名的一个页面,也就是上图中的C。A和C是同域的,即使是A不能访问C,但是C却可以通过parent.parent来访问A。为了演示,我配置了以下host:
aw目录结构如下:
www/aw
----app.py
----templates
--------index.html
--------cross.html
app.py源码:
#coding: utf8
import os
from datetime import timedelta
from flask import Flask, render_template
import urllibapp = Flask(__name__)app.secret_key = os.urandom(24)
app.permanent_session_lifetime = timedelta(seconds=24 * 60 * 60)@app.route('/')
def index():return render_template('index.html', **dict(upload_url='http://www.file.com:6667/upload'))@app.route('/cross.html')
def cross():return render_template('cross.html')if __name__ == '__main__':app.run(host="0.0.0.0",port=int("6666"),debug=True)
index.html源码:
<!DOCTYPE html>
<html>
<head><meta charset="utf-8"><title>aw</title><meta name="author" content="" /><meta http-equiv="X-UA-Compatible" content="IE=7" /><meta name="keywords" content="aw" /><meta name="description" content="aw" /><script type="text/javascript" src="http://cdn.staticfile.org/jquery/2.1.0/jquery.min.js"></script>
</head>
<body>
<form enctype="multipart/form-data" action="{{ upload_url }}" method="POST" target="upload_iframe"><input name="UploadName" type="file" /><input type="submit" value="上传" />
</form>
<iframe id="upload_iframe" name="upload_iframe" width="0" height="0" style="display: none;"></iframe>
<script type="text/javascript">
// 上传完成回调
function uploadComplete(data)
{console.log('上传完成:' + data);
}
</script>
</body>
</html>
cross.html源码:
<!DOCTYPE html>
<html>
<head><meta charset="utf-8"><title>aw cross</title><meta name="author" content="" /><meta http-equiv="X-UA-Compatible" content="IE=7" /><meta name="keywords" content="aw cross" /><meta name="description" content="aw cross" /><script type="text/javascript" src="http://cdn.staticfile.org/jquery/2.1.0/jquery.min.js"></script>
</head>
<body>
<script type="text/javascript">
$(function() {var href = location.href;var index = href.indexOf('?');if (index < 0){var data = 'result=upload_error';}else{var data = href.substring(index + 1);}// 将数据通过调用parent.parent.uploadComplete方法来传递parent.parent.uploadComplete(data);
});
</script>
</body>
</html>
file目录结构如下:
www/file
----app.py
app.py源码:
#coding: utf8
import os
from datetime import timedelta
from flask import Flask, request, render_template
import urllibapp = Flask(__name__)app.secret_key = os.urandom(24)
app.permanent_session_lifetime = timedelta(seconds=24 * 60 * 60)@app.route('/upload', methods=['POST'])
def index():'''忽略上传文件处理细节,直接返回数据'''cross_html = 'http://www.aw.com:6666/cross.html?result=upload_complete'return '<iframe width="0" height="0" style="display:none;" src="%s"></iframe>' % cross_htmlif __name__ == '__main__':app.run(host="0.0.0.0",port=int("6667"),debug=True)
这样就实现了跨域回调,知道了原理其实就不难了,如有需要可进行封装,如实现跨域检测,如果是同域则使用同域的方式进行回调,如果是跨域,则使用跨域的方式进行回调。并且可实现多文件上传方案。
关于超时
上传超时是必须处理的上传错误之一。对于iframe上传(这里并没有特指同域或跨域)来说,超时机制将会限制整个上传所占用的时间,这是有必要的,否则如果网络异常,前端将一直显示正在上传中,这是极不友好的用户体验。另一方面也是为了安全考虑。
其实实现iframe的上传超时机制非常简单。通过setTimeout在固定时间后去remove iframe,当然如果上传是成功的则会提前clearTimeout。所以如果setTimeout成功执行则肯定是超时了,否则就是上传完成(至于是上传成功或上传失败则由服务器端返回的状态码来确定)。比如:
index.html源码:
<!DOCTYPE html>
<html>
<head><meta charset="utf-8"><title>aw</title><meta name="author" content="" /><meta http-equiv="X-UA-Compatible" content="IE=7" /><meta name="keywords" content="aw" /><meta name="description" content="aw" /><script type="text/javascript" src="http://cdn.staticfile.org/jquery/2.1.0/jquery.min.js"></script>
</head>
<body>
<form enctype="multipart/form-data" action="{{ upload_url }}" method="POST" target="upload_iframe"><input name="UploadName" type="file" /><input type="submit" value="上传" />
</form>
<iframe id="upload_iframe" name="upload_iframe" width="0" height="0" style="display: none;"></iframe>
<script type="text/javascript">
// 上传完成回调
function uploadComplete(data)
{timeout_id && clearTimeout(timeout_id);console.log('上传完成:' + data);
}
var timeout_id = setTimeout(function() {$("#upload_iframe").remove();uploadComplete("上传超时")
}, 10000);
</script>
</body>
</html>
大致上就是这样,这是很常用的跨域上传方案,有必要认真理解并加以实践。
转载于:https://my.oschina.net/goal/blog/200058
Flask: 跨域上传的回调方案相关推荐
- php js跨域上传文件,Jquery实现跨域异步上传文件步骤详解
这次给大家带来Jquery实现跨域异步上传文件步骤详解,Jquery实现跨域异步上传文件的注意事项有哪些,下面就是实战案例,一起来看一下. 先说明白 这个跨域异步上传功能我们借助了Jquery.for ...
- java 跨域上传_java使用webuploader实现跨域上传详解
前言 项目中使用webuploader进行文件上传,需要用到跨域,查看webuploader的issues发现是支持上传的,但是他们写的回复都是不清不白的,有点迷糊:想了半天才知道咋回事,也可能是我比 ...
- wangeditor 请求头_跨域上传 · wangEditor2使用手册 · 看云
**首先,wangEditor的跨域上传已经不再支持 IE8.9 浏览器.** ---- IE10 及以上浏览器在使用跨域上传时,需要服务器端的配合,对`response`设置以下`head`信息: ...
- 解决使用elementUI框架el-upload跨域上传时session丢失问题
解决使用elementUI框架el-upload跨域上传时session丢失问题 参考文章: (1)解决使用elementUI框架el-upload跨域上传时session丢失问题 (2)https: ...
- 全网最直接简单。百度富文本跨域上传文件到文件服务器
看了很多文章其实也有很多办法,实现跨域上传.现在讲我目前所用的方法.只实现的多图上传.单图上传失败. 接下来必须认真的看完文章. 当前我用的 版本为UEditor1.4.3. 这里主要是实现重写接收文 ...
- springboot上传图片到宝塔Linux(本地上传和跨域上传)
1.浏览器访问宝塔面板的图片需要的配置-- 点击文件www-->server-->tomcat-->conf-->server.xml 可以自己修改,请在宝塔面板和服务器上放 ...
- SpringMvc+ajax实现文件跨域上传
最近开始学习SpringMVC框架,在学习数据绑定的时候,发现可以使用@RequestParam注解绑定请求数据,实现了文件上传.但是如果一个项目是前后端分离的,前端系统向后端服务上传文件该怎么解决了 ...
- 允许多域名跨域 php,php后端控制可跨域的域名,允许图片跨域上传
跨域问题经常需要面对,前端需要做的比较直接 要么选择ajax异步提交,XML或者jsonp,要么表单提交 jsonp基本可以搞定大部分跨域问题,但问题也比较明显,只能通过get方式提交 并且jsonp ...
- java 跨域上传,Java如何利用Ajax完成跨域上传图片的功能介绍
这篇文章主要介绍了Java使用Ajax实现跨域上传图片功能,需要的朋友可以参考下 说明 : 图片服务器是用Nginx搭建的,用的是PHP语言 这个功能 需要 用到两个js文件: jquery.js和j ...
- java后台图片跨域上传
跨域的原因 跨域的实现原理 本地服务器源码 图片服务器源码 测试 本地服务器 跨域的原因 在项目开发的过程中,我们经常需要用到图片上传操作,传统的做法是我们将其上传到项目的所在目录中,比如说项目的 ...
最新文章
- html 怎么自动让图片居中显示,css中怎样让图片居中显示?
- 看完这篇文章你还敢说你懂JVM吗?
- datetimepicker 时间不更新_iOS 14.2 正式版推送:新增人体检测,这些功能值得更新...
- 如何以学习单片机为契机,逐步成为优秀的工程师
- System.out.println 在idea控制台输出的中文乱码问题
- 第二十二篇 jQuery 学习4 内容和属性
- VSFTPD 上传文件 200 227 553错误
- pyspark读取ES数据报array错误
- 小啊呜产品读书笔记001:《邱岳的产品手记-03》第04+05讲 如何当好AI时代的产品经理 06讲 产品案例分析·TheGuardian的文本之美
- 【游戏逆向】浅谈某平台调试软件检测分析
- 新墨斯智能鞋让你成为健康达人
- 决定局域网特性的三要素是什么
- 2020中兴开发岗笔试题
- DDR SDRAM原理介绍
- IDEA推出新字体,极度舒适
- SAP 04-CONTAINER 使用DOCKING停靠容器示例
- 如何申请芬兰居留许可(留学)
- 植物大战僵尸变态辅助开发系列教程(E语言实现和VC6实现)(下)
- 全网最牛掰的 12306 抢票神器,助力抢到春节回家的票
- java实现ppt/pptx转图片,转pdf的两种方式之一 poi
热门文章
- cmd怎么导入mysql文件,使用cmd工具如何导入大容量sql文件到mysql数据库
- c语言 camp;gt与camp;lt,那位高人告诉我怎么复习c语言二级啊?????
- go语言中关于文件的操作+工作目录的拼接
- 多用户访问SSAS cube权限设置
- filename.whl is not supported wheel on this platform 部分第三方库无法安装的解决办法
- 2层框架结构柱子间距_钢筋混凝土楼板层其施工方法有哪些不同
- linux web目录安全设置,[LNMP]Linux的Web环境的安全配置
- 从CDN到云计算,网宿科技定制化打造“双龙头”格局
- Flyweight模式
- Java千百问_05面向对象(013)_泛型如何使用