如何替代即将淘汰的Flash方案?

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

本文由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 送你一份技术课程大礼包!

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

原文地址:https://www.cnblogs.com/qcloud1001/p/9803086.html

时间: 2024-08-30 17:35:21

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

学习已经被淘汰的flash

一.基本知识介绍 网站动画的分类:二维动画和三维动画 ? 二维动画分类: 1.GIF动画 2.flash动画 flash软件:是矢量软件 ? 选中带有点,并且可以任意变形的对象,叫形状 逐帧动画:在时间帧上逐帧绘制帧内容 帧的分类和作用: ? 1.普通帧(延时帧):延长画面的停留时间(F5) 2.关键帧:原地复制上一帧所有内容(F6) 3.空白关键帧:插入一个空帧(F7) ? flash文件保存格式: 1. fla可以编辑的源文件格式 2. swf导出的影片格式,用于网站 ? ? ? ? 运动补

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

刚学习Java不久,今天遇到一个问题,需要在方法中修改传入的对象的值,确切的说是需要使用一个方法,创建一个对象,并把其引用返回,熟悉C#的我的第一反应就是C#中的ref/out关键字,结果发现Java中没有类似的关键字,所以只能想想如何解决此问题. 参数传递:方法的参数传递有两种,一种是值传递,一种是引用传递,但是其实都是拷贝传递. 值传递:就是把传递的[数据本身拷贝一份],传入方法中对其进行操作,拷贝的是值.引用传递:就是把指向某个对象的[引用拷贝一份],传入方法中通过此引用可以对对象进行操作

Python2即将淘汰,分享python3 才能用的特性(13个)

特性 1: 高级解包 使用解包交换变量非常方便,在 python3 中,这个特性得到了加强,现在你可以这样做: a, b, *rest = range(10) print('a:', a) print('b:', b) print('rest:', rest) ##> a: 0 ##> b: 1 ##> rest: [2, 3, 4, 5, 6, 7, 8, 9] rest 可以在任何位置,比如这样: a, *rest, b = range(10) print('rest', rest)

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

Java解析OFFICE(word,excel,powerpoint)以及PDF的实现方案及开发中的点滴分享 在此,先分享下写此文前的经历与感受,我所有的感觉浓缩到一个字,那就是:"坑",如果是两个字那就是"巨坑"=>因为这个需求一开始并不是这样子的,且听我漫漫道来: 一开始客户与我们商量的是将office和PDF上传,将此类文件解析成html格式,在APP端调用内置server直接以html"播放" 经历一个月~,两个月~,三个月~~~

视频直播方案(加强版)

一 相关技术说明 1 概述 1.1通用直播总体架构 Java在用于视频开发时主要采用的技术框架是FFmpeg和OpenCV.数据库和其他的功能实现可以使用Java Web的相关技术就可以实现. FFmpeg主要有两种网络传输协议:RTSP.RTMP RTSP;实时流传输协议,是TCP/IP协议体系中的一个应用层协议.RTSP在体系结构上位于RTP和RTCP之上,它使用TCP或UDP完成数据传输. RTMP;实时消息传输协议)的首字母缩写.该协议基于TCP,是一个协议族,包括RTMP基本协议及RT

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

Atitit.office word  excel  ppt pdf 的web在线预览方案与html转换方案 attilax 总结 1. office word  excel pdf 的web预览要求1 1.1. 显示效果要好1 1.2. 可以自定义显示界面1 1.3. 不需要控件,兼容性好1 1.4. 支持编辑操作1 2. 纯html预览解决之道(自由的格式)1 3. 转换swf flash方案2 4. 转换pdf方式..更多的浏览器已经直接支持pdf格式查看2 5. 控件方式2 6. Hyb

0004 ubuntu下为opera26.0安装flash

问题:在ubuntu14.10下装了opera最新版本无法安装flash,网上教程中的usr/lib下找不到opera目录! 解决办法: 先说下安装opera,直接打开opera官网,官网会自动检查到你的系统为linux,直接安装即可. 因为 Adobe Flash 不再支持 linux Google 便开发了PepperFlashPlayer来替代原来的 Adobe Flash 下面介绍 PepperFlashPlayer 在安装方法 第一步:安装,在终端里输入下面的命令 sudo apt-g

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

ubuntu14.0.4中系统自带的chromium无法播放flash,后来查了下,得知chromium已经不支持adobe flash了,用户可使用pepper flash替代.安装pepper flash的方法: sudo apt-get update sudo apt-get install pepperflashplugin-nonfree

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

前言 尽管每辆汽车都有后视镜,但不可避免地都存在一个后视镜的盲区,倒车雷达则可一定程度帮助驾驶员扫除视野死角和视线模糊的缺陷,提高驾驶安全性.上一节已经分析清倒车雷达的语音模块(上一节),本节将深入分析测距模块的设计. 一.倒车雷达的发展 第0代倒车雷达:“倒车请注意”!只要司机挂上倒档,它就会响起.(然并卵) 第1代倒车雷达:在距车1.5~1.8m处有障碍物,蜂鸣器就会工作,距离越近蜂鸣器越急促.(没有显示,考验司机耳力) 第2代倒车雷达:数码管显示距离数字,3色波段绿.黄.红分别表示安全.警