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.总结

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

较友好的Web文件下载用户体验实例的更多相关文章

  1. web测试总结—用户体验

    一.什么是用户体验 用户体验,英文叫做user experience,缩写为UE,或者UX.一个较常见的定义是“指用户访问一个网站或者使用一个产品时的全部体验.他们的印象和感觉,是否成功,是否享受,是 ...

  2. 改善用户体验 Web前端优化策略总结

    前端是庞大的,包括HTML.CSS.Javascript.Image.Flash等等各种各样的资源.前端优化是复杂的,针对方方面面的资源都有不同的方式.那么,前端优化的目的是什么? 1. 从用户角度而 ...

  3. Web开发中设置快捷键来增强用户体验

    从事对日外包一年多以来,发现日本的无论是WinForm项目还是Web项目都注重快捷键的使用,日本人操作的时候都喜欢用键盘而不是用鼠标去点,用他们的话来说"键盘永远比鼠标来的快",所 ...

  4. Progressive Web App是一个利用现代浏览器的能力来达到类似APP的用户体验的技术——不就是chrome OS吗?

    什么是Progressive Web App? Progressive Web App是一个利用现代浏览器的能力来达到类似APP的用户体验的技术,由Google实现,让浏览器打开的网址像APP一样运行 ...

  5. Web优化躬行记(4)——用户体验和工具

    一.用户体验 用户体验(UE/UX)是指一个人使用一个特定产品.系统或服务时的行为.情绪与态度,还包含用户对于系统的功能.易用和效率的感受,因此用户体验在本质上可以视为一个人对于系统的主观感受与主观想 ...

  6. web设计经验<二>设计华丽的用户体验的6个热门技巧

    你是否曾经下载了一个应用,却发现它“很难使用”?对于大多数智能手机用户来说,答案是肯定的. 有趣的是,每四个手机应用中就有一个应用在下载后被“打入冷宫”. 如果一个应用能够吸引一个人下载并且打开它,但 ...

  7. Django Web开发【6】使用Ajax增强用户体验

    Ajax及其优点 Ajax实际上就是指异步Javascript与XML,它包含以下技术: HTML与CSS Javascript XMLHttpRequest XML Ajax技术让客户端与服务器实现 ...

  8. web开发性能优化---用户体验篇

    怎样从技术角度怎样增强用户体验.都是非常多平台都在做的事情,依据个人实际经验碰到几种体验做下总结. 1.降低页面刷新白屏 适当使用ajax技术.改善刷新白屏现象. 2.信息提醒,邮件.站内信.短信在购 ...

  9. 通过 .NET NativeAOT 实现用户体验升级

    前言 TypedocConverter 是我先前因帮助维护 monaco-editor-uwp 但苦于 monaco editor 的 API 实在太多,手写 C# 的类型绑定十分不划算而发起的一个项 ...

随机推荐

  1. 搞不清FastCgi与PHP-fpm之间是个什么样的关系(转载)

    刚开始对这个问题我也挺纠结的,看了<HTTP权威指南>后,感觉清晰了不少. 首先,CGI是干嘛的?CGI是为了保证web server传递过来的数据是标准格式的,方便CGI程序的编写者. ...

  2. BSTestRunner——一个丑在路上的python unnitest HTML报告生成Runner

    今天忽然看到HTMLTestRunner的样式,第一眼的感觉是样式有点过时了,稍微看了下源码,果然最后更新时间是几年前,由于实现比较简单,所以顺手将样式改一下. 效果图 设计思想 既然有UI,那么如果 ...

  3. Mac OS X Terminal 101:终端使用初级教程

    Mac OS X Terminal 101:终端使用初级教程 发表于 2012 年 7 月 29 日 由 Renfei Song | 文章目录 1 为什么要使用命令行/如何开启命令行? 2 初识Com ...

  4. 使用Eclipse进行远程调试【转】

    今天决定做件有意义的事,写篇图文并茂的blog,为什么要图文并茂?因为很多事可能用语言也说不明白,从以前我发表的一篇文章可以看得出来,http://blog.csdn.net/sunyujia/arc ...

  5. Swift 3 新特性和迁移详解

    写在前面 Swift 3.0 正式版发布了差不多快一个月了,断断续续的把手上和 Swift 相关的迁移到了Swift 3.0.所以写点小总结. 背景 代码量(4万行) 首先,我是今年年初才开始入手 S ...

  6. 计算A/3,不用除法

    int DividedBy3(int A) { ; ; i <= ; i += ) p += A << i; return (-p); }

  7. (笔记)Linux内核学习(八)之定时器和时间管理

    一 内核中的时间观念 内核在硬件的帮助下计算和管理时间.硬件为内核提供一个系统定时器用以计算流逝的时间.系 统定时器以某种频率自行触发,产生时钟中断,进入内核时钟中断处理程序中进行处理. 墙上时间和系 ...

  8. Promise 使用心得

        this.testPromise=function(){         return new Promise(function(resolve,reject){             co ...

  9. Android之NDK开发

    转自:http://www.cnblogs.com/devinzhang/archive/2012/02/29/2373729.html 一.NDK产生的背景 Android平台从诞生起,就已经支持C ...

  10. Unity 之 人物换装

    http://www.cnblogs.com/mcwind/archive/2011/02/18/1957453.html  原理 一. SkinedMeshRender:该对象负责网格绘制.主要数据 ...