zoukankan      html  css  js  c++  java
  • 较友好的Web文件下载用户体验实例

    1.实际需求整理与分析

    该问题起源于为公司做的一个B/S架构的游戏静态数据管理工具,其中有一个需求是点击页面上的一些按钮要下载文件,可能根据按钮类型的不同需要转换下载.json、.zip、.xlsx等文件格式,为了好的体验,当时考虑这个功能应做到以下几点:

    1.1.页面跳转

    下载文件时,页面不会刷新、跳转、添加页面(单页面且所有数据交互都通过ajax,所以要做到这点)

    1.2.错误处理

    在遇到意外情况,如:文件不存在、服务器异常,同样不允许跳转或者刷新

    1.3.错误提示

    在1.2的基础上,应能根据错误对用户做出提示。

    1.4.需求分析

    做到第1点很简单,现代浏览器对于响应头信息Content-Type为application/octet-stream都会提示下载,而不会跳转或者刷新页面。但是直接这样做会带来2,3点的问题,如果文件不存在或者服务器处理出现了异常,则会跳转到404、5**的错误界面。

    查了一些方法,综合以后准备利用iframe实现第2点,利用iframe与父页面的交互实现第2点。

    2.实现抽象示例

    这里以最基本的文件来演示需求的实现。(这里只写了前端的实现,完全实现需要后端处理,对后端的要求这里只做简单介绍)

    2.1.功能及文件抽象

    这里我根据需求抽象了4个文件:

    index.html        提供给用户点击交互的页面(主页)

    iframe.html    主页的iframe中加载的页面,该页面body内容默认只有需要加载的js和一个id为json_data,内容为空的div节点(错误提示的时候会有值,后面会介绍),主页面的iframe元素应全程保持隐藏状态

    index.js            主页加载的逻辑js文件

    iframe.js           iframe页面加载的js文件。

    2.2.代码实现

    下面介绍实例代码,(注:依赖jquery,且只有符合上面需求的功能):

    2.2.1.index.html

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <title>Index</title>
    
    </head>
    <body>
        <!-- 这里还至少应该有个下载的按钮或者其他能够提供下载交互的组件 -->
        <script type="text/javascript" src="jquery.js"></script>
        <script type="text/javascript" src="index.js"></script>
    </body>
    </html>

    2.2.2.index.js

    /**
     * 文件下载方法
     * 
     * @param string strUrl 下载文件的请求地址
     */
    function DownLoad(strUrl) {
        
        var download_iframe = $('#download_iframe');
        // 没有iframe就添加一个
        if (download_iframe.length === 0) {
            download_iframe = $('<iframe></iframe>');
            download_iframe.attr('id', 'download_iframe');
            download_iframe.attr('src', 'iframe.html');
            download_iframe.css('display', 'none');
            $('body').append(download_iframe);
        } else {
            // 有的话直接重新载入页面
            download_iframe.attr('src','iframe.html?' + Math.random());
        }
        // 在该iframe加载完成后执行iframe.js内部的Download方法。
        var content = download_iframe[0].contentWindow;
        download_iframe.one('load', function () {
            content.DownLoad(strUrl);
        });
    }
    
    /**
     * 处理服务器下载文件返回异常信息
     *
     * @param object jsonTxt 服务器返回的json信息序列化后的对象
     * 
     */
    function processDownloadErr(jsonTxt) {
        alert(jsonTxt.Msg); // 这里只做最简单的弹出处理,实际使用的时候应根据自己项目中有的提示插件进行提示
    }

    上面代码中会在第一次调用Download时创建一个iframe加载iframe.html;以后再次调用Download则会直接重新加载iframe的内容。

    processDownloadErr方法用于处理iframe传过来的错误消息。

    2.2.3.iframe.html

    一般情况下iframe内容:

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <title>iframe</title>
    </head>
    <body>    
        <div id="json_data">

    </
    div> <script type="text/javascript" src="jquery.js"></script> <script type="text/javascript" src="iframe.js"></script> </body> </html>

    有错误或者自定义提示时的内容:

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <title>iframe</title>
    </head>
    <body>    
        <div id="json_data">
            {"Msg":"该ID对应的文件不存在!"}
        </div>
        <script type="text/javascript" src="jquery.js"></script>
        <script type="text/javascript" src="iframe.js"></script>
    </body>
    </html>

    2.2.4.iframe.js

    /**
     * 实际下载文件的方法
     *
     * @param string strUrl 文件的下载地址
     * 该函数可以根据实际需要扩充,比如需要传递参数则再加一个{}类型的形参。
     */
    function DownLoad(strUrl) {
        // 查找页面上的form表单(因为前面规定,iframe.html中的body默认是空的,所以如果能找到的话必定是下载的form)
        var form = $('form');
        // 如果找不到,则添加一个
        if (form.length == 0) {
            form = $("<form>");   // 定义一个form表单
            form.attr('style', 'display:none');   // 在form表单中添加查询参数
            form.attr('target', ''); // 这里默认给提交自己,
            form.attr('method', 'post'); // 这里我设定为post,如果需要自定义的话可以再给Download方法再添加一个参数
        }
        form.attr('action', strUrl);
        $('body').append(form);  // 将表单放置在页面body中 
        form.submit();
    }
    
    // 默认#json_data内容为空,只有在有错误信息的时候才会获得内容且提交给iframe的顶级节点处理
    (function() {
        var json_text = $.trim($('#json_data').text());
        if (json_text !== '') {
            top.processDownloadErr($.parseJSON(json_text).Data);
        }
    })();

    iframe的Download方法被调用时会向body添加一个form表单,并按传入的url提交请求。因为该页面是在iframe中的,所以如果服务器返回404或者5xx等错误也不会引起主页面的跳转。

    服务器发现下载文件出现问题的时候,仍返回iframe.html,在其#json_data中设置错误信息(如2.2.3中的内容)。这个时候json_text会获取到值,交由顶层页面处理。

    2.2.5.服务器逻辑要求

    这里对于服务器逻辑的要求,也就是能够满足在检测文件状态或者参数有误的时候,仍能返回iframe.html,且设置错误信息。

    3.总结

    上面应该算是不依赖任何插件下,较简单的一种增加浏览器下载文件友好度的实现。因整体项目毕竟为工作项目,所以就不贴真实源码了,以后在自己其他业余时间做的项目中会用到这块逻辑,到时候再贴上博客。只希望本文的一些思路能对大家有帮助。

  • 相关阅读:
    C++内联函数
    C++类中创建线程
    windows下搭建Redis集群
    tcpdump截帧工具使用
    使用gdb调试应用程序
    工作之用
    primecoin服务常用命令和参数说明
    Windows mysql默认字符集修改
    primecoin在ubuntu16.04上部署服务:
    ubuntu磁盘分配和挂载
  • 原文地址:https://www.cnblogs.com/yaoh/p/5090431.html
Copyright © 2011-2022 走看看