文件上传之渐进式增强

一、前言

随着HTML5规范的提出,我们又多了一种上传方式的选择。相对企业信息系统而言,互联网产品的用户群体要广泛很多,不同的用户群体通常会选择不同的浏览器,不同的浏览器对HTML5规范的支持程度不同。单一的上传方式根本无法满足所有用户。我们需要采用渐进式增强的上传方式为用户提供较好的上传体验。

二、案例分析

我们以QQ相册作为案例,分析渐进式增强的上传方式。

先看一下QQ相册的图片预览功能:

是不是很炫?以上界面是用Flash实现的,现在我禁用Flash:

再看看QQ相册,先提示我安装浏览器插件:

我选择不安装,界面就变成这样:

我们看到了丑陋的input type=‘file‘了。底部可以看到提示语:请安装Flash或使用极速上传。

我选择极速上传并安装浏览器插件,再启用Flash插件,重新进入相册上传界面:

界面是不是更炫了?连本地磁盘的图片都被读取了。浏览器插件是不是很可怕?

由此,我们可以看出QQ相册的图片上传功能,渐进式增强的优先级是这样的:

浏览器插件 -> Flash -> 普通上传

整个过程压根儿没考虑HTML5的解决方案。也许跟QQ相册的用户群体有关。

三、139邮箱文件上传渐进式增强

通过对业界其它产品的分析再结合我们自己产品的用户特征,139邮箱文件上传渐进式增强的优先级是这样的:

浏览器插件 -> HTML5 -> Flash -> 普通上传

什么?为什么139邮箱的上传方式HTML5优先于Flash?原因如下:

(1)、HTML5是浏览器原生提供的能力,默认情况下无法被禁用,而且不需要另外加载文件,可减少http请求。

(2)、有些浏览器会默认禁用Flash插件,比如FireFox25默认情况下就是禁用Flash的,需要单击地址栏左侧的红色图标才能启用Flash插件:

(3)、第三个原因也是最重要的原因,公司某些领导偏爱FireFox浏览器又不知道怎么启用Flash插件。领导的爱好决定了产品的走向,是不是很蛋疼?如果你们公司的领导偏爱其它浏览器,请自行调整优先级。

四、能力检测

确定渐进式增强的优先级之后,接下来就需要对用户的浏览器做能力检测:是否安装自定义的浏览器插件、是否支持HTML5上传、是否安装Flash插件。

判断是否安装自定义的浏览器插件,完整代码如下:

function isUploadControlSetup() {
    var setup = false;

    if (window.ActiveXObject) {//ie
        try {
            if (new ActiveXObject("Cxdndctrl.Upload")) {
                setup = true;
            }
        } catch (ex) {
            try {
                if (new ActiveXObject("ExCxdndCtrl.ExUpload")) {
                    setup = true;
                }
            } catch (e) {
                console.log(ex);
                console.log(‘创建ActiveXObject("Cxdndctrl.Upload")及ActiveXObject("ExCxdndCtrl.ExUpload")对象失败!‘);
            }
        }
    } else if (navigator.plugins) {//firefox chrome
        var mimetype = navigator.mimeTypes["application/x-richinfo-cxdnd3"];

        setup = (mimetype && mimetype.enabledPlugin) ? true : false;
    }

    return setup;
}

粗体字部分需要替换成创建自己的浏览器插件实例对象所需的字符串参数。如139邮箱小工具参数值为:Cxdndctrl.Upload

判断是否支持HTML5的上传方式,完整代码如下:

function isSupportHtml5Upload() {
    if (window.File && window.FileList && window.FileReader && window.Blob && window.FormData && window.Worker && "withCredentials" in (new XMLHttpRequest)) {
        return true;
    }
    return false;
}

判断是否安装Flash插件,IE浏览器需要通过try{}catch(){}试探创建ActiveXObject实例,标准浏览器可迭代navigator.plugins,完整的代码如下:

function getVersionInIE() {
    var version = 0;
    var axo;

    // NOTE : new ActiveXObject(strFoo) throws an exception if strFoo isn‘t in the registry
    try {
        // version will be set for 7.X or greater players
        axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.7");
        version = axo.GetVariable("$version");
    } catch (e) {
    }

    if (!version) {
        try {
            // version will be set for 6.X players only
            axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.6");

            // installed player is some revision of 6.0
            // GetVariable("$version") crashes for versions 6.0.22 through 6.0.29,
            // so we have to be careful.

            // default to the first public version
            version = "WIN 6,0,21,0";

            // throws if AllowScripAccess does not exist (introduced in 6.0r47)
            axo.AllowScriptAccess = "always";

            // safe to call for 6.0r47 or greater
            version = axo.GetVariable("$version");

        } catch (e) {
        }
    }

    if (!version) {
        try {
            // version will be set for 4.X or 5.X player
            axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.3");
            version = axo.GetVariable("$version");
        } catch (e) {
        }
    }

    if (!version) {
        try {
            // version will be set for 3.X player
            axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.3");
            version = "WIN 3,0,18,0";
        } catch (e) {
        }
    }

    if (!version) {
        try {
            // version will be set for 2.X player
            axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash");
            version = "WIN 2,0,0,11";
        } catch (e) {
        }
    }

    if (version !== 0) {
        var match = version.match(/(\d+),(\d+).*$/);

        if (match[0]) {
            version = Number(match[1] + "." + match[2]);
        } else {
            version = 0;
        }
    }

    return version;
}

function getVersionInOthers() {
    var v = 0;
    if (navigator.plugins && navigator.plugins.length > 0 && navigator.plugins["Shockwave Flash"]) {
        var plugins = navigator.plugins["Shockwave Flash"];
        for (var i = 0; i < plugins.length; i++) {
            var swf = plugins[i];
            if (swf.enabledPlugin && (swf.suffixes.indexOf("swf") != -1) && navigator.mimeTypes["application/x-shockwave-flash"]) {
                var match = plugins.description.match(/ (\d+(?:\.\d+)?)/);
                if (match) {
                    var v = parseInt(match[1]);
                    break;
                }
            }
        }
    }
    return v;
}

五、HTML5上传方式分析

断点续传,秒传都是建立在文件分块的基础之上的,分块上传需要读取文件块的内容,并计算文件内容的MD5值,读取文件内容需要用到FileReader,而计算MD5值需要用到Worker

为什么我们需要使用Worker来计算MD5值?

因为计算MD5值需要消耗较多的CPU时间,浏览器本身是采用单线程模式工作的,为了避免MD5值的计算阻塞其它JS代码的执行,我们需要使用Worker对象创建新线程完成MD5值的计算。

六、什么?你是IE6用户而且还有洁癖不想安装任何浏览器插件,下图红圈按钮就是为你量身定制的,欢乐的戳它吧

文件上传之渐进式增强

时间: 2024-10-10 07:17:38

文件上传之渐进式增强的相关文章

Javascrpt无刷新文件上传

最近工作中遇到上传文件问题,主要需求是一步点击上传,兼容ie8+,当时用的dojox/form/uploader控件,这两天扒了一下源码,明白了原理拿出来分享一下. 总体思路如下: 1.对于支持XMLHttpRequest2的浏览器使用FormData通过ajax上传 2.对于ie10一下的浏览器使用iframe异步上传,还需后台服务器做相应处理,这部分也是dojo/request/iframe上传文件的原理. 一.使用FormData上传文件 FormData最频繁使用的功能就是表单序列化及创

java实现大文件上传

文件上传是最古老的互联网操作之一,20多年来几乎没有怎么变化,还是操作麻烦.缺乏交互.用户体验差. 一.前端代码 英国程序员Remy Sharp总结了这些新的接口 ,本文在他的基础之上,讨论在前端采用HTML5的API,对文件上传进行渐进式增强: * iframe上传 * ajax上传 * 进度条 * 文件预览 * 拖放上传 1.1 传统形式 文件上传的传统形式,是使用表单元素file,参考 http://www.ruanyifeng.com/blog/2012/08/file_upload.h

java+web+大文件上传下载

文件上传是最古老的互联网操作之一,20多年来几乎没有怎么变化,还是操作麻烦.缺乏交互.用户体验差. 一.前端代码 英国程序员Remy Sharp总结了这些新的接口 ,本文在他的基础之上,讨论在前端采用HTML5的API,对文件上传进行渐进式增强:     * iframe上传  * ajax上传  * 进度条  * 文件预览  * 拖放上传 1.1 传统形式 文件上传的传统形式,是使用表单元素file,参考 http://www.ruanyifeng.com/blog/2012/08/file_

局域网超大文件上传

文件上传是最古老的互联网操作之一,20多年来几乎没有怎么变化,还是操作麻烦.缺乏交互.用户体验差. 一.前端代码 英国程序员Remy Sharp总结了这些新的接口 ,本文在他的基础之上,讨论在前端采用HTML5的API,对文件上传进行渐进式增强:     * iframe上传  * ajax上传  * 进度条  * 文件预览  * 拖放上传 1.1 传统形式 文件上传的传统形式,是使用表单元素file,参考 http://www.ruanyifeng.com/blog/2012/08/file_

HTML5 增强的文件上传域

在HTML5以前,HTML的文件上传域的功能具有很大的局限性,这种局限性主要体现在如下两点: 每次只能选择一个文件进行上传 客户端代码只能获取被上传文件的文件路径,无法访问实际的文件内容 一.FileList对象和File对象 HTML5为type='file' 的<input/>元素增加了两个属性. accept:该属性控制允许上传的文件类型.该属性为一个或多个MIME类型字符串.多个MIME类型字符串之间应以都好分割. multiple:该属性设置是否允许选择多个文件 JavaScript

Facade模式实现文件上传(Flash+HTML5)

一.前言 确定了渐进式增强的上传方式,接下来我们需要将上传功能从具体的业务逻辑中剥离出来,作为公共组件供业务层调用.这就要求我们必须对业务层隐藏上传细节,只暴露统一的上传API.这时候大家是不是跟我一样想到了Facade模式? 二.Facade模式实现文件上传,代码示例: /* 上传组件,IE浏览器默认flash上传,其它浏览器html5 示例: var fileUpload = new FileUpload({ container: document.getElementById("uploa

异步文件上传组件 Uploader

Uploader是非常强大的异步文件上传组件,支持ajax.iframe.flash三套方案,实现浏览器的全兼容,调用非常简单,内置多套主题支持 和常用插件,比如验证.图片预览.进度条等,广泛应用于淘宝网,比如退款系统.爱逛街.二手.拍卖.我的淘宝.卖家中心.导购中心等. Uploader的特性 支持ajax.flash.iframe三种方案,兼容所有浏览器.(iframe不推荐使用) 多主题支持,可以自己定制主题 丰富的插件支持 支持多选批量上传 支持上传进度显示 支持取消上传 支持图片预览(

【黑马程序员】第12课:文件上传&文件下载&注解

<pre> day12 上节内容回顾 1.jstl的标签 *if  choose *forEach <c:forEachvar="l" items="${list}"> 2.jsp开发模式 *模型一 *模型二(mvc模式) **mvc模式 ***m:模型,使用javabean ***v:视图,使用jsp ***c:控制器,使用servlet *dao模式:数据访问对象,专注于对数据库的操作 **首先创建接口,在接口里面定义操作数据库的方法 *

基于Metronic的Bootstrap开发框架经验总结(5)--Bootstrap文件上传插件File Input的使用

Bootstrap文件上传插件File Input是一个不错的文件上传控件,但是搜索使用到的案例不多,使用的时候,也是一步一个脚印一样摸着石头过河,这个控件在界面呈现上,叫我之前使用过的Uploadify 好看一些,功能也强大些,本文主要基于我自己的框架代码案例,介绍其中文件上传插件File Input的使用.关于Uploadify的控件介绍,可以参考我之前的随笔介绍<基于MVC4+EasyUI的Web开发框架形成之旅--附件上传组件uploadify的使用>. 1.文件上传插件File In