定制jQuery File Upload为微博式单文件上传

原文链接:http://avnpc.com/pages/single-file-upload-component-by-jquery-file-upload


jQuery File Upload是一个非常优秀的上传组件,主要使用了XHR作为上传方式,并且利用了相当多的现代浏览器功能,所以可以实现诸如批量上传、超大文件上传、图片预览、拖拽上传、上传进度显示、跨域上传等功能。

美中不足的是jQuery File Upload的默认UI比较复杂,集成了全部功能,让jQuery File Upload的定制变得比较繁琐。

尝试用jQuery File Upload制作了一个类似微博图片上传的单文件式上传Demo,将一些要点记录下来备忘。最终效果如下图:

jQuery File Upload Demo

jQuery File Upload的最简模型

jQuery File Upload包含了一堆文件,首先需要弄清楚的是最核心的部分是哪些,根据官方的例子可以知道,一个最简单的jQuery File Upload上传组件,必须包括以下文件:

  • jQuery核心库,建议使用jQuery 1.8以上版本
  • js/vendor/jquery.ui.widget.js : jQuery UI Widget
  • js/jquery.iframe-transport.js : 扩展iframe数据传输
  • js/jquery.fileupload.js : jQuery File Upload核心类
  • js/cors/jquery.xdr-transport.js 在IE下应载入此文件解决跨域问题

此时只需要加载一个上传按钮

<input id="fileupload" type="file" name="files[]" data-url="server/php/" multiple>

以及一行代码

$('#fileupload').fileupload();

就完成了一个最基本的上传组件。这个最简单的上传组件可以将选中的文件以表单形式提交到data-url约定的URL,同时提供了足够多的设置和基础事件可供扩展。

jQuery File Upload的简单扩展

对于最简模型,稍加扩展就可以实现一些比较常用的功能,比如可以在上传完毕后可以显示一个简单的结果:

$('#fileupload').fileupload({done: function (e, data) {$.each(data.result, function (index, file) {$('<p/>').text(file.name + ' uploaded').appendTo($("body"));});}
});

或者显示上传进度,配合一些进度条组件就可以构成一个上传进度条

$('#fileupload').fileupload('option', {progressall: function (e, data) {var progress = parseInt(data.loaded / data.total * 100, 10);console.log(progress + '%');}
});

等等。只要多阅读手册就可以配合项目做更具体的扩展开发。

XHR响应为Json时IE的下载BUG

这里需要特别注意的是,由于jQuery File Upload都是采用XHR在传递数据,服务器端返回的通常是JSON格式的响应,但是IE会将这些JSON响应误认为是文件传输,然后直接弹出下载框询问是否需要下载。

解决这个问题的方法是必须将相应的Http Head从

Content-Type: application/json

更改为

Content-Type: text/plain

具体的实现根据服务端不同有所区别,比如ZF2中可以在Controller中这样写:

 $this->getServiceLocator()->get('Application')->getEventManager()->attach(\Zend\Mvc\MvcEvent::EVENT_RENDER, function($event){$event->getResponse()->getHeaders()->addHeaderLine('Content-Type', 'text/plain');}, -10000);

这也是我在stackoverflow上的对ZF2更改最终响应类型的一个回答

jQuery File Upload UI的构成与说明

为了引入更多功能,jQuery File Upload在上面最简模型的基础上又实现了一套jQuery File Upload UI,也就是官方给出的最终Demo,这套UI额外提供了以下功能:

  • 最大/最小文件限定 Options.maxFileSize / Options.mixFileSize
  • 文件类型限定,通过正则表达式检测文件名实现 Options.acceptFileTypes
  • 选择文件后自动上传 Options.autoUpload
  • 上传文件数量限制,通过上传后将选择文件按钮置为Disabled实现 Options.maxNumberOfFiles
  • 上传模板,就是选择文件后显示预览的html代码 Options.uploadTemplate
  • 下载模板,当文件上传完毕后显示的html代码 Options.downloadTemplate

等等,同时还增加了一系列新的接口和事件,具体都可以查阅官方手册。

具体对应到文件为:

  • JavaScript-Templates : JS模板引擎
  • JavaScript-Load-Image : 图片预览功能
  • js/jquery.fileupload-ui.js & css/jquery.fileupload-ui.css : UI核心类,CSS可以替换旧式的上传控件为统一的按钮
  • js/jquery.fileupload-fp.js:进度条扩展功能

也许正是因为附加功能太多,各功能之间耦合非常重,jQuery File Upload UI显得不够友好,主要体现在:

  • 上述功能均无法拆分,必须统一全部加载
  • 各功能需要界面存在相应元素,如果缺少某些元素,包括JS模板内的元素,整个UI无法正常工作
  • JS模板引擎对标签配对非常严格,标签如果遗漏也有可能引起UI无法正常工作

所以经验之谈是,在定制jQuery File Upload UI时,如果UI无法工作。首先检查js文件是否全部加载,然后检查页面元素是否齐全,再次检查JS模板标签是否严格配对,最后还可以查看页面是否有重复调用fileupload()方法。

jQuery File Upload UI构成元素

UI的部件都是硬编码的HTML class,无法更改。核心的几个部件为

全局控制按钮 (必须)

    <div class="fileupload-buttonbar"><span class="fileinput-button"><input type="file" name="files[]" multiple></span><button type="submit" class="start">Start upload</button><button type="reset" class="cancel">Cancel upload</button><button type="button" class="delete">Delete</button><input type="checkbox" class="toggle"></div>

最外层容器为.fileupload-buttonbar,内部包含

  • 文件选择按钮 .fileinput-button (必须),内部必须包裹一个input:file
  • 开始上传按钮 .start
  • 取消上传按钮 .cancel
  • 删除按钮 .delete
  • 文件勾选按钮 .toggle

整体上传进度 (可选)

<div class="fileupload-progress"><div class="progress"><div class="bar" style="width:0%;"></div></div><div class="progress-extended"></div>
</div>

最外层容器为.fileupload-progress,内部包含

  • 上传进度条容器.progress
  • 上传进度条 .bar
  • 上传进度文本 .progress-extended

文件显示容器 (必须)

<div class="files"></div>

.file容器是最重要的UI部件,上传时的文件预览模板以及上传完毕后的文件显示模板都将显示在这里。

文件预览模板 (必须)

<script id="template-upload" type="text/x-tmpl">
{% for (var i=0, file; file=o.files[i]; i++) { %}
<div class="template-upload">{% if (file.error) { %}<div class="error">{%=file.error%}</div>{% } else { %}<div class="preview"><span class="fade"></span></div><div class="name"><span>{%=file.name%}</span></div><div class="size"><span>{%=o.formatFileSize(file.size)%}</span></div><div class="progress progress-success progress-striped active" role="progressbar" aria-valuemin="0" aria-valuemax="100" aria-valuenow="0" style="height:5px;"><div class="bar" style="width:0%;"></div></div><span class="start">{% if (!o.options.autoUpload) { %}<button>Start Upload</button>{% } %}</span>{% } %}<span class="cancel"><button>Cancel</button></span>
</div>
{% } %}
</script>

这部分逻辑不难读懂,由于文件选择是多选的,所以被选择文件一开始以数组方式存放,循环输出。即使我们加入最大文件只能上传一个,这里得到的仍然是数组形式。

当文件有任何错误时,如文件类型被禁止,文件大小不符合约定,会得到file.error。文件检测没有问题,则可以用以下元素控制当前文件:

  • 开始上传当前文件按钮.start (必须)
  • 取消上传当前文件按钮.cancel (可选)
  • 当前文件上传进度.progress (可选)

上传后文件回调显示模板 (必须)

<script id="template-download" type="text/x-tmpl">
{% for (var i=0, file; file=o.files[i]; i++) { %}
<div class="template-download">{% if (file.error) { %}<div class="error">{%=file.error%}</div><span class="cancel"><button class="btn btn-block"><i class="icon-ban-circle"></i>Cancel</span>{% } else { %}<div class="preview"><img src="{%=file.thumbnail_url%}"></div><div class="name"><span>{%=file.name%}</span></div><div class="size"><span>{%=o.formatFileSize(file.size)%}</span></div><div class="delete"><button data-type="{%=file.delete_type%}" data-url="{%=file.delete_url%}">Delete</button></div>{% } %}
</div>
{% } %}
</script>

这一部分的o.files完全来自服务器端的json响应,所以模板内容可以自由发挥。唯一被定制的元素为删除按钮.delete。 点击这个按钮会向按钮中指定的url发送请求,比如

<div class="delete"><button data-type="DELETE" data-url="/file/1">Delete</button></div>

点击后则会用DELETE方式发送HTTP请求

DELETE /file/1

jQuery File Upload UI工作流程

有了上面罗列的UI元素,就可以拼凑出一个简单的jQuery File Upload UI工作流程:

  1. 用户点击.fileinput-button选择要上传的文件(多个)
  2. 文件选择后,文件信息被整理为数组置入文件预览模板#template-upload
  3. 模板引擎循环处理文件信息并生成模板.template-upload
  4. 每生成一个模板,模板就被插入到文件显示容器.files的最后。
  5. 用户点击上传按钮.start上传,文件信息被转换为XHR请求至服务器端
  6. UI获得服务器端生成JSON响应文件
  7. JSON响应信息也被整理成数组置入回调显示模板#template-download
  8. 模板引擎循环处理文件信息并生成模板.template-download
  9. 每生成一个模板,会将此模板替换对应的.template-upload部分

定制过程

有了上面的基础,要个性化的定制jQuery File Upload就简单了很多:

限制文件类型

由于没有使用Flash空间,上传的文件选择框是无法限制文件类型的,所以所谓的限制文件类型,只能让用户选择文件之后,用file.error显示一个错误信息。例如本次需要限定可上传的文件为图片,那么Options指定:

acceptFileTypes:  /(\.|\/)(gif|jpe?g|png)$/i

即可。

在Google Chrome浏览器中,可以用input:file原生支持文件类型限定,可以配合使用:

<input type="file" name="upload[]"  accept="image/png, image/gif, image/jpg, image/jpeg">

不过在客户端做再多的限定也只是提升用户体验,不能真正保证安全性,所以不要忘记了在服务器端做同样的类型检测。

文件数量限制

只需在Options指定

maxNumberOfFiles : 1

即可。jQuery File Upload UI的处理方式是当用户上传一个文件后,文件选择按钮被置为Disabled。

这同样只是客户端的小把戏,真正想要严格的约束用户只能上传一个文件还是需要在服务器端通过Session做更加复杂的控制。

文件大小限制

Options中指定

maxFileSize: 5000000

即只允许单文件最大5MB。

Firefox disable bug

在Firefox环境下测试是,发现如果将文件数量限制为1,选择一次文件,刷新页面之后文件选择按钮会莫名其妙的被加上一个Disabled属性,导致无法点击。所以最终我们的初始化代码为:

var uploader = $("#fileupload");
uploader.fileupload({dataType: 'json',autoUpload: false,acceptFileTypes:  /(\.|\/)(gif|jpe?g|png)$/i,maxNumberOfFiles : 1,maxFileSize: 5000000 
});
uploader.find("input:file").removeAttr('disabled');

最后就是界面的一些调整,完整代码在EvaEngine的File模块下,点击查看.

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/276693.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

vb趣味编程弹球小游戏_最好玩的微信小游戏集合,总有一款是你没玩过的

大家好&#xff0c;这里是小雅龙生活趣味时间&#xff0c;自从17年微信推出小游戏程序以来&#xff0c;微信小游戏行业可谓是炙手可热&#xff0c;知道2019年不断有许许多多的微信小游戏如雨后春笋般的生根发芽。下面就由我带大家来看看今年最好玩&#xff0c;最受欢迎的微信小…

開發MOSS2007 Masterpage的一些經驗

一直在做MOSS平臺的Masterpage開發,碰到很多的問題,總結了一些經驗,特此記錄: masterpage的所有的ContentPlaceholder詳細解釋見以下網址:http://www.cnblogs.com/WinYoung/archive/2007/06/25/791766.html 1.如果應用masterpage以后IE狀態欄出現""網頁指令碼錯誤訊息…

Golang——垃圾回收GC(2)

1 垃圾回收中的重要概念 1.1 定义 In computer science, garbage collection (GC) is a form of automatic memory management. The garbage collector, or just collector, attempts to reclaim garbage, or memory occupied by objects that are no longer in use by the pro…

java gui框架_推荐!程序员整理的Java资源大全

构建这里搜集了用来构建应用程序的工具。Apache Maven&#xff1a;Maven使用声明进行构建并进行依赖管理&#xff0c;偏向于使用约定而不是配置进行构建。Maven优于Apache Ant。后者采用了一种过程化的方式进行配置&#xff0c;所以维护起来相当困难。Gradle&#xff1a;Gradle…

帆软报表(finereport)控件背景色更改

setTimeout(function() {$(.fr-trigger-btn-up).css({"background-color": "#003399" });}, 100); 转载于:https://www.cnblogs.com/Williamls/p/11571586.html

开心网分析,师从“中国缘”

作者&#xff1a;麦田   一&#xff0c;师从“中国缘” 开心网从08年“爆发”之后&#xff0c;网上出现很多评论文章。几乎100%的评论文章都谈到了开心网“不可思议”的爆发增长速度&#xff0c;比如几个月就进入了alexa前500等等。但是&#xff0c;几乎没有一篇文章提到“开心…

HTML5+CSS3+JQuery1.9 输入框切换和Div失焦模拟

Div失焦原理&#xff1a;判断document点击对象是否在Div容器以内&#xff0c;否则触发事件 需要脚本&#xff1a;jquery-1.9.1.js 下载地址&#xff1a;http://download.csdn.net/detail/dmtnewtons/5807757 <!DOCTYPE> <html> <head> <meta http-equ…

资本冬天已至,开发者却可以着眼未来

云&#xff0c;在国内外都已成为软件开发者的首选服务。纵观历史&#xff0c;在云计算发展的这些年里&#xff0c;不管云上做了多少产品和服务&#xff0c;其实都离不开云最本质的价值体系&#xff1a;自服务、高弹性、按需提供、免运维&#xff0c;这些特性也让云服务天然成为…

mybatis 大于_酸爽!IDEA 中这么玩 MyBatis,让编码速度飞起!

作者&#xff1a;Orsoncnblogs.com/java-class/p/6237564.html1. 搭建 MyBatis Generator 插件环境a. 添加插件依赖 pom.xmlb. 配置文件 generatorConfig.xmlc. 数据库配置文件 jdbc.propertiesd. 配置插件启动项2.项目实战a. 比如在一个项目 我们要删除某个小组下某个用户的信…

Java的三种代理模式完整源码分析

Java的三种代理模式&完整源码分析 Java的三种代理模式&完整源码分析 参考资料&#xff1a; 博客园-Java的三种代理模式 简书-JDK动态代理-超详细源码分析 [博客园-WeakCache缓存的实现机制](https://www.cnblogs.com/liuyun1995/p/8144676.html) 静态代理 静态代理在使…

scatter函数_matplotlib.pyplot常用函数scatter讲解大全(三)

前言这篇文章再来总结一个常用画图函数scatter-散点图。参数常用参数示例import matplotlib.pyplot as plt import numpy as np#导入需要的包 datanp.random.multivariate_normal([0,1],[[1,0],[0,1]],200)#准备数据&#xff0c;二维正态分布plt.rcParams["axes.unicode_m…

如何彻底卸载MySQL

本文摘自&#xff1a;http://www.heiqu.com/show-64764-1.html 内容为&#xff1a; 由于安装MySQL的时候&#xff0c;疏忽没有选择底层编码方式&#xff0c;采用默认的ASCII的编码格式&#xff0c;于是接二连三的中文转换问题随之而来&#xff0c;就想卸载了重新安装MYSQL&…

vue-cli项目模板的一些思考

之前有个想法&#xff0c;就是要利用vue写一套ui。然后当时也没有搞清楚到底怎么写。 几经周转吧&#xff0c;通过付费的方式在gitbook上面找到了答案。 找到答案之后再看我们正在开发的项目&#xff0c;看伙伴写的代码&#xff0c;突然发现完全可以按照写ui组件库的方式调整目…

flex基于svn协同开发

想做一个游戏&#xff0c;正好有人陪我做。于是想到用flex来协同开发。本来是想使用cvs&#xff0c;可是结果捣鼓了半天&#xff0c;也没个结果——估计是最近没怎么看电影&#xff0c;IQ降下来了。于是改用svn。 参考资料&#xff1a;http://www.flashmagazine.com/tutorials/…

cookie与session详解

session与cookie是什么?session与cookie属于一种会话控制技术.常用在身份识别&#xff0c;登录验证&#xff0c;数据传输等.举个例子&#xff0c;就像我们去超市买东西结账的时候&#xff0c;我们要拿出我们的会员卡才会获取优惠.这时候&#xff0c;我们怎么识别这个会员卡真实…

c++万能头文件_初学Python,与C对比

✎背景学了一学年的C的基础&#xff0c;下学年开课Python&#xff0c;现在正在自学中...C也不是不学了&#xff0c;而是之前买了一本《CPrimer》在学校里&#xff0c;就准备先学一下Python&#xff0c;下学期利用自由时间接着学习C。这里分析了一下二者的优缺点&#xff0c;供大…

listen(int fd, int backlog)中的backlog含义

1. listen(int fd, int backlog)中的backlog不能限制连接数量??? http://bbs.chinaunix.net/viewthread.php?tid870564 backlog应该是未完成3次握手连接和已完成3次握手而未被accept的两对列之和.不知道我说的对不? 如果要控制连接数量,是不是要自己编码控制...下面的可以…

本地无法启动MySQL服务,报的错误:1067,进程意外终止---解决

原文链接&#xff1a;http://blog.csdn.net/shenhonglei1234/article/details/5928873 在本地计算机无法启动MYSQL服务错误1067进程意外终止 这种情况一般是my.ini文件配置出错了 首先找到这个文件&#xff1a; 默认安装路径 C:/Program Files/MySQL/MySQL Server 5.1/my.ini …

一篇文章助你理解Python3中字符串编码问题

前几天给大家介绍了unicode编码和utf-8编码的理论知识&#xff0c;以及Python2中字符串编码问题&#xff0c;没来得及上车的小伙伴们可以戳这篇文章&#xff1a;浅谈unicode编码和utf-8编码的关系和一篇文章助你理解Python2中字符串编码问题。下面在Python3环境中进行代码演示&…

Express框架开发知识点总结

express --viewpug myapp 以上语句在当前工作目录中创建名为 myapp 的 Express 应用程序&#xff0c;采用的模板是jade。 以前还在纠结使用hbs模板引擎或者ejs模板&#xff0c;实际上只要将--view后面的pug换成hbs&#xff08;使用的是Handlebars模板引擎&#xff09;&#xff…