欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~

本文由MarsBoy发表于云+社区专栏

| 导语 Web技术飞速发展的如今,我们在感受新技术带来的便捷和喜悦的同时,也时常在考虑着一个问题:老技术如何迁移。正如本文的主题一样,Flash技术在早年风靡在Web领域,曾经发挥着无尽力量的一个工具正逐渐失去了其重要性。由于性能,兼容性,版权问题,Flash的市场正在消退,曾经靠Flash实现的功能和特性如何完美得进行迁移呢,本文将简单谈一谈Flash的几个常见的特性的替代方案。

1.视频播放(Play Video)

我们知道Flash可以播放.swf文件的动画视频,而且具有很强的控制功能,以前很多Web视频播放器都是基于Flash去实现的。包括embed标签,都是如此。所有视频源为swf的文件的视频都需要借助Flash去播放。

解决方案:

在移动端设备上,使用HTML5的video标签基本没有问题。 在PC上,IE低版本(IE8-)浏览器上除了Flash目前没有其它办法 在PC上,IE9+和其它现在浏览器,采用HTML5标签。 综合来说,可以统一用以下一段代码实现兼容:

<video width="400" height="300" controld>
<!-- mp4格式适用于IE9+,Chrome,Safari -->
<source src="test.mp4" type="video/mp4"></source>
<!-- ogg格式适用于FireFox,Opera,Chrome -->
<source src="test.ogg" type="video/ogg"></source>
<!-- webm格式适用于FireFox,Opera,Chrome -->
<source src="test.webm" type="video/webm"></source>
<!-- object需要Flash支持,当IE8-时考虑 -->
<object data="test.mp4" width="400" height="300">
<!-- embed需要Flash支持,当IE8-时考虑 -->
<embed src="test.swf" width="400" height="300">
</object>
</video>

2.跨域请求(Corss Origin Request)

2.1使用Flash进行跨域请求的方案实现

目前在PC端a.qq.com的页面请求b.qq.com的一个接口是理论上跨域的一个请求,旧版本浏览器特别是只支持XMLHTTPRequest Level1的浏览器,需要访问跨域请求,要么使用jsonp,要么只能使用Flash。 使用Flash进行跨域需要做的事情是

1.a.qq.com的js与Flash交互 2.Flash校验安全性,检查b.qq.com下根目录的crossDomain.xml文件的控制访问属性 3.Flash作为中间代理请求b.qq.com 4.Flash将请求结果返回给a.qq.com的js 图1简明扼要的描述了这个过程。

图1 Flash跨域请求

2.2 去Flash跨域如何实现

情况一:CORS(Cross-Origin Resource Sharing)【后端需改造】

条件:要使用CORS,必须在支持XmlHttpRequest Level2的浏览器中(IE10+和其它现代浏览器) 做法:设置withCredentials头,然后结合后台设置的Access-Control-Allow-Origin头进行控制,进行跨域即可。相关代码如下: 前端JS:

$.ajax({
url:"http://b.qq.com/api/xxx.php",
type:"POST",
xhrFields:{
withCredentials:true
},
success:function(){
//...
},
fail:function(){
//...
}
})

后端PHP:

<?php
//b.qq.com的接口中添加Access-Control-Allow-Origin头
header("Access-Control-Allow-Origin:http://a.qq.com");

情况二:中转代理请求【建议】

我们回到同源策略,如果要请求b.qq.com下的一个接口,我们从b.qq.com下的页面发起请求,是遵循同源策略的。那么我们可以在接口域名下放一个统一的html文件,用于代理我们请求b.qq.com的接口,然后将结果告诉a.qq.com就可以了。 这种情况下要解决2个主要问题: 1.cookie如何发送 2.a.qq.com与b.qq.com的代理页面前端通信 其实两个问题是一个问题,a.qq.com下的cookie我们是可以获取到的,同样的cookie我们可以种在b.qq.com下的。问题归结到第二个问题,如何在前端实现a.qq.com和b.qq.com两个页面之间的通信。 有两个方法:

1.使用HTML5规范的PostMessage特性

主要核心逻辑代码可以参考: 【a.qq.com页面代码】

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<script>
//a.qq.com中逻辑:
var $proxyFrame=$("<iframe style='display:none' src='http://b.qq.com/proxy.html'></iframe>").appendTo(document.body);
//等待iframe中转页面load完毕
$proxyFrame.on("load",function(){
//调中转页面
$proxyFrame.get(0).contentWindow.postMessage({
api:"/xx/y",
data:{
a:1,
b:2
},
cookie:document.cookie//带过去的cookie
});
//回调
$(window).on("message",function(e){
var event=e.originalEvent;
if(event.origin=="http://b.qq.com"){
console.log("response data:",event.data);
}
})
}) </script>
</body>
</html>

【b.qq.com页面代码】

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<script>
//b.qq.com中逻辑:
$(window).on("message",function(e){
var event=e.originalEvent;
if(event.origin=="http://a.qq.com"){
var api=event.data.api;
var data=event.data.data;
var cookie=event.data.cookie;
//种植cookie
//.........种植cookie的操作
//代理请求接口
$.ajax({
url:api,
data:data,
//.......
success:function(result){
//将response返回给a.qq.com
window.parent.postMessage(result,"*")
},
fail:function(){ }
})
}
})
</script>
</body>
</html>

以上demo简单解决了前端跨域通信,跨域带cookie等问题,在逻辑上完全可以实现跨域通信。但是对于不支持PostMessage特性的老版浏览器是行不通的。比如IE8-浏览器就不能很好的支持PostMessage特性。这种情况下我们采用另外一种中转跨域的方案:降子域通信。 下面介绍第二种方法:降子域通信:

2.不支持PostMessage时,降子域通信

由于a.qq.com和b.qq.com都是属于qq.com下的子域,同源策略在前端页面中判定依据是document.domain而不是location.host。而document.domain可写,可以人为更改到其父域名。这样a.qq.com和b.qq.com的两个页面都可以自行降到qq.com。这样就可以直接进行通信。 主要核心逻辑代码可以参考: 【a.qq.com页面代码】

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<script>
//a.qq.com中逻辑:
document.domain="qq.com";
var $crossFrame=$("<iframe style='display:none' src='http://b.qq.com/proxy.html'></iframe>").appendTo(document.body);
//等待iframe中转页面load完毕
$crossFrame.on("load",function(){
//回调
window['callback']=function(result){
//收到响应
console.log("receive response:",result);
}
//调中转页面中的方法直接请求
$crossFrame.get(0).contentWindow.request({
api:"/xx/y",
data:{
a:1,
b:2
}
});
}) </script>
</body>
</html>

【b.qq.com页面代码】

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<script>
//b.qq.com中逻辑:
document.domain="qq.com";
window.request=function(api,data){
$.ajax({
url:api,
data:data,
//.......
success:function(result){
//将response返回给a.qq.com
window.parent.callback(result,"*")
},
fail:function(){ }
})
}
</script>
</body>
</html>

在实际改造过程中,如果后端结果过多,或者改造不方便,可以直接采用第二种方式——中转代理的方式进行改造。其原理示意图总结如下:

图2 去Flash跨域请求改造指导图

3.文件上传

3.1 背景

其实文件上传是HTML规范内的,理论上不需要使用Flash去做。但是随着ajax技术的兴起,Web 2.0时代的到来,input表单的提交改成ajax提交,页面无刷新的形式。但是这种形式下对于文件这类二进制文件无法提交,IE下本来有ActiveX 的FSO可以操作,但是插件的执行需要IE安全机制允许,很多情况下用户体验不好,而且兼容性也不是很好。于是这种背景下,FLash又担当起了一个新的功能:文件上传。 著名的jquery插件,ajaxupload.js就是用的Flash进行文件提交。

3.2去Flash上传

如何不使用Flash,上传文件,而且保证页面不刷新,是我们在去Flash上传工作中需要做的核心。下面针对不同的浏览器提供两套方案:

3.2.1 【第一套方案】HTML5获取文件信息用FormData提交

条件:支持HTML5 FileReader 和FormData 特性 做法:

1.获取input表单的files对象 2.实例化FileReader对象,并解析files对象 3.解析之后输出base64编码的文件数据 4.base64的数据传入FormData 5.ajax提交FormData

参考demo如下:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<input type="file" name="test" id="test" />
<script>
$("#test").change(function(e){
var files=e.target.files;
va fr=new FileReader();
fr.onload=function(e){
var fm=new FormData();
fm.append("file_test",e.target.result);
//额外参数
fm.append("sExtend","test");
//提交ajax
$.ajax({
url:'http://b.qq.com/cgi/',
type:"POST",
dataType:json,
data:fm,
processData: false, // 不会将 data 参数序列化字符串
contentType: false, // 根据表单 input 提交的数据使用其默认的 contentType
success:function(result){
console.log(result);
},
fail:function(){
console.log("failed");
}
});
}
fr.readAsDataURL(files[0]);
});
</script>
</body>
</html>

3.2.2 【第二套方案】低版本浏览器中用模拟表单提交

条件:无任何条件,支持任何浏览器 做法:

1.在页面上构建一个隐藏的iframe 2.在页面上构建一个form表单,表单中包含文件表单和其它附加字段表单,target设为上述iframe的id 3.上传文件动作触发时,调用form的submit方法 4.iframe中加载上传cgi,返回结果与父窗口通信,如果iframe与cgi跨域,则参考【第二部分:跨域请求】进行处理

参考demo如下:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>DEMO-上传文件</title>
</head>
<body>
<!-- 以a.qq.com上传到b.qq.com/upload/为例 -->
<form action="http://b.qq.com/upload/" enctype="multipart/form-data" method="post" target="postframe" name="fileform">
<!-- 文件上传按钮 -->
<input type="file" name="file_1" />
<!-- 隐藏的附加字段 -->
<input type="hidden" name="sExtend1" value="test1" />
<input type="hidden" name="sExtend2" value="test2" />
</form> <iframe src="" frameborder="0" style="display:none;" id="postframe"></iframe> <script>
//监听文件基本信息
$("[name=file_1]").change(function(e){
var files=e.target.files;
if("undefined" == typeof files && e.target.value){
//IE9-
files=[];
try{
files=[new ActiveXObject("Scripting.FileSystemObject").GetFile(e.target.value)];
}catch(err){
files=[{
name:e.target.value,
type:"unkown"
}];
}
if(!files.length){
files=[{
name:e.target.value,
type:"unkown"
}];
}
}
//获取文件信息
console.log(files); }) //上传 $("[name=fileform]").submit(); //回调 window.fileCallback=function(result){
//处理result
console.log("文件上传成功");
}
</script>
</body>
</html>

总结 本文给出了笔者在实际工作中遇到的最常见的去Flash改造的三种场景,现以表格的形式简单概括如下:

现代H5 早期低版本IE等
视频播放 使用H5的video标签 没办法只能使用FLash,如果不用Flash,建议提醒用户升级浏览器
跨域提交请求 使用CORS,前后端结合 中转代理(PostMessage或者降域)
Ajax文件上传 使用FileReader+FormData封装 模拟表单提交到iframe
结语

去Flash不仅是对实现方案的一种兼容改造,更是对早已成熟的新技术新思路的运用。目前而言,不管是因为政策原因,还是因为性能或者其它兼容性原因,去Flash改造都是重要和紧迫的,本文是笔者在实际工作过程中总结出的最常见的三种去Flash场景和改造方案,供参考,不足之处还请不吝指正。

相关阅读

再论 ASP.NET 中获取客户端IP地址

从零开始的Spring Session

【每日课程推荐】机器学习实战!快速入门在线广告业务及CTR相应知识

此文已由作者授权腾讯云+社区发布,更多原文请点击

搜索关注公众号「云加社区」,第一时间获取技术干货,关注后回复1024 送你一份技术课程大礼包!

海量技术实践经验,尽在云加社区

如何替代即将淘汰的Flash方案?的更多相关文章

  1. CS5211完全替代兼容LT7211|PS8625|CH7511方案|EDP转LVDS|Capstone CS5211

    CH7511|LT7211|PS8625替代方案--Capstone CS5211AN 设计EDP转LVDS优势方案原理图+PCB板设计 CH7511|LT7211|PS8625这三款都是专门用于设计 ...

  2. 学习已经被淘汰的flash

    一.基本知识介绍 网站动画的分类:二维动画和三维动画   二维动画分类: 1.GIF动画 2.flash动画 flash软件:是矢量软件   选中带有点,并且可以任意变形的对象,叫形状 逐帧动画:在时 ...

  3. 完全替代RTD2166方案设计|CS5202直接替代RTD2166|DP转VGA 方案

    CS5202可以直接PIN TO PIN替代RTD2166 整体方案设计只需改动一个电阻和一个电容,在性能和参数设定方面与RTD2166可以达成一致,且成本比RTD2166要低,性价比更高.CS520 ...

  4. Java中替代C# ref/out 关键字方案:

    刚学习Java不久,今天遇到一个问题,需要在方法中修改传入的对象的值,确切的说是需要使用一个方法,创建一个对象,并把其引用返回,熟悉C#的我的第一反应就是C#中的ref/out关键字,结果发现Java ...

  5. 替代联阳IT6564方案|CS5262替代IT6564|设计DP转HDMI+VGA扩展坞方案

    联阳IT6564:带嵌入式MCU的单芯片4通道DisplayPort1.2到HDMI2.0/VGA转换器 联阳IT6564是一种高性能的单芯片显示端口到HDMI和VGA转换器.IT6564FN结合Di ...

  6. Java解析OFFICE(word,excel,powerpoint)以及PDF的实现方案及开发中的点滴分享

    Java解析OFFICE(word,excel,powerpoint)以及PDF的实现方案及开发中的点滴分享 在此,先分享下写此文前的经历与感受,我所有的感觉浓缩到一个字,那就是:"坑&qu ...

  7. ubuntu中chromium无法播放flash,安装flash

    ubuntu14.0.4中系统自带的chromium无法播放flash,后来查了下,得知chromium已经不支持adobe flash了,用户可使用pepper flash替代.安装pepper f ...

  8. [硬件项目] 2、汽车倒车雷达设计——基于专用倒车雷达芯片GM3101的设计方案与采用CX20106A红外线检测芯片方案对比

    前言 尽管每辆汽车都有后视镜,但不可避免地都存在一个后视镜的盲区,倒车雷达则可一定程度帮助驾驶员扫除视野死角和视线模糊的缺陷,提高驾驶安全性.上一节已经分析清倒车雷达的语音模块(上一节),本节将深入分 ...

  9. Atitit.office word  excel  ppt pdf 的web在线预览方案与html转换方案 attilax 总结

    Atitit.office word  excel  ppt pdf 的web在线预览方案与html转换方案 attilax 总结 1. office word  excel pdf 的web预览要求 ...

随机推荐

  1. Alpha阶段敏捷冲刺(五)

    1.站立式会议 提供当天站立式会议照片一张 2.每个人的工作 (有work item 的ID),并将其记录在码云项目管理中: 昨天已完成的工作. 祁泽文:实现了个人遗忘曲线图 徐璐琳:完成了微信Web ...

  2. MessageFormat.format()和String.format()

    MessageFormat 提供了以与语言无关方式生成连接消息的方式.使用此方法构造向终端用户显示的消息. MessageFormat 获取一组对象,格式化这些对象,然后将格式化后的字符串插入到模式中 ...

  3. 实验8 LCD8*8点阵

    1.控制点阵红绿交替显示,分别从上到下,从左到右循环闪烁三次 接线: P0接J12.P1接J20.P2接J19 /** 1.控制点阵红绿交替显示,分别从上到下,从左到右循环闪烁三次 **/ #incl ...

  4. ASP.Net MVC OA项目笔记<一>

    1.1.1 新建空白解决方案CZBK.ItcastOA 1.2.1 添加类库 1.2.2 同上添加多个类库 生成的 class1.cs先不用删除,删了的后,后面可能没办法直接点引用 1.3.1 添加表 ...

  5. vue.js - 2

    最近开发公司vue前端项目,做一下笔记,偶尔上来查漏补缺 组件操作: 使用flag标识符结合v-if和v-else切换组件 页面结构: <div id="app"> & ...

  6. 【环境学习】ThinkPHP5 5.0.22/5.1.29 远程代码执行漏洞

    环境保留:2019.4.4-4.10 环境搭建: 这里我使用的是:vulhub vulhub目录结构:vulhub/thinkphp/5-rcess 测试地址(开放一段时间供大家学习):http:// ...

  7. 【spring cloud】服务启动后正常,但是无法上线,一直处于down状态

    spring cloud eureka 如果出现某个应用实例 down(1), 说明 spring admin 健康检测没有通过导致 eureka 注册中心不会把这个实例从列表中删除掉. 这样所有使用 ...

  8. 【Junit4】:要点随笔

    1. 引入Junit4的Maven依赖 <dependencies> <dependency> <groupId>junit</groupId> < ...

  9. MySQL 逻辑物理备份测试

    目录 逻辑备份 mysqldump 普通备份 mysqlpump 并行备份 mysqlpump 压缩并行备份 mydumper 并行备份 mydumper 并行压缩备份 小结 物理备份 xtrabac ...

  10. day 39 jq 学习入门2

    ---恢复内容开始--- 前情提要: jq 是用来降低js 的工作的一个组件 一:利用jq 实现动画效果 <!DOCTYPE html> <html lang="en&qu ...