Facade模式实现文件上传(Flash+HTML5)
一、前言
/*
上传组件,IE浏览器默认flash上传,其它浏览器html5
示例:
var fileUpload = new FileUpload({
container: document.getElementById("uploadBtn"),
onselect: function (files) {
var self = this;
$(files).each(function (i, n) {
updateUI(n);
});
setTimeout(function () { //异步,等待onselect函数return后才能调用upload
self.upload();
}, 10);
},
onprogress: function (fileInfo) {
updateUI(fileInfo);
},
oncomplete: function (fileInfo, responseText) {
updateUI(fileInfo); }
});
*/
function FileUpload(options) {
var uploader=null;
if (options) {
//为什么要多创建一级div容器?flash 的activex创建后,再改变位置会引起activex对象失效,所以要在创建前就定好位
var div = document.createElement("div");
div.id = "flashUploadDiv";
document.body.appendChild(div);
var c = $(options.container);
//绝对定位到上传按钮的坐标,flash本身为透明遮罩
$(div).css({
position: "absolute",
left: c.offset().left + "px",
opacity:0,
top: c.offset().top + "px"
}); if ($.browser.msie || options.uploadType == "flash") { //flash上传方式
var url = "Richinfo_annex_upload.swf";
var so = new SWFObject(url, "flashupload", c.width(), c.height());
so.addParam("wmode", "transparent");
so.write("flashUploadDiv"); options.activexObj = document.getElementById("flashupload"); window.JSForFlashUpload = new FlashUpload(options);
uploader = JSForFlashUpload; } else { $(div).html(['<form style="" enctype="multipart/form-data" id="fromAttach" method="post" action="" target="frmAttachTarget">',
'<input style="height: ', c.height(), 'px;width:', c.width(), 'px" type="file" name="uploadInput" id="uploadInput" multiple="true">',
'</form>',
'<iframe id="frmAttachTarget" style="display: none" name="frmAttachTarget"></iframe>'].join(""));
options.uploadInput = document.getElementById("uploadInput");
uploader = new Html5Upload(options); }
} this.upload = function () {//触发上传请求
//alert("uploader.load");
uploader.upload();
},
this.cancel = function () {//取消上传
uploader.cancel();
}
this.getUploadFiles = function () {//获取上传队列
uploader.getUploadFiles();
} $.extend(options, this);//继承FileUpload的能力
}
var FlashUpload = function(options){ var resultObject = {
activexObj: options.activexObj,
upload:function(){
this.activexObj.uploadAll();
},
cancel: function () {
this.activexObj.cancel();
},
getUploadUrl: function () {
return this.agent.getUploadUrl();
},
getUploadFiles: function () {
return this.uploadFiles;
},
onload: function (param) {
this.agent = {};
if (options) {
this.agent = options;
}
param["filter"] = ["images图片(*.jpg;*.png;*.bmp)", "video(*.flv;*.avi;*.rmvb)"];
param["uploadFieldName"] = "filedata";
//options["filter"] = ["eml邮件(*.eml)"];
//options["filter"] = ["所有文件(*.*)"];
return param;
},
onselect: function (xmlFileList, jsonFileList) { for (var i = 0; i < jsonFileList.length; i++) {
jsonFileList[i].fileName = decodeURIComponent(jsonFileList[i].fileName);
jsonFileList[i].state = "waiting";
/*if (jsonFileList[i].fileSize > 100000) { //大于100K不上传
jsonFileList.splice(i, 1);
i--;
}*/
}
//uploadView.onselect(jsonFileList);
this.agent.onselect && this.agent.onselect(jsonFileList); this.uploadFiles = jsonFileList;
return jsonFileList;
},
onprogress: function (taskId, sendedSize, uploadSpeed, fileInfo) {
fileInfo.taskId = taskId;
fileInfo.sendedSize = sendedSize;
fileInfo.percent = Math.round((sendedSize / fileInfo.fileSize) * 100);
fileInfo.state = "uploading";
fileInfo.fileName = decodeURIComponent(fileInfo.fileName);//防止乱码,flash里面做了encode
//alert(fileInfo.percent);
this.agent.onprogress && this.agent.onprogress(fileInfo);
},
oncomplete: function (taskId, responseText, fileInfo) {
fileInfo.taskId = taskId;
fileInfo.state = "complete";
fileInfo.fileName = decodeURIComponent(fileInfo.fileName);//防止乱码,flash里面做了encode
this.agent.oncomplete && this.agent.oncomplete(fileInfo, responseText);
},
onerror: function (taskId, errorCode, errorMsg) {
alert("文件上传失败:" + errorMsg);
this.agent.onerror && this.agent.onerror(errorMsg);
},
onmouseover: function () { },
onmouseout: function () { },
onclick: function () {
return true;//返回false不会弹出文件选择框
//alert("onclick");
} }
return resultObject;
}
var Html5Upload = function (options) {
var resultObject = {
uploadInput: null,
currentFile: null,
uploadFiles:[],//待上传的文件
completeFiles:[],//已完成的文件
init: function () {
var self = this;
this.agent = options;
this.uploadInput = options.uploadInput;
this.uploadInput.onclick = this.onclick;
this.uploadInput.onchange = function () {
var files = this.files;
var result = [];
for (var i = 0; i < files.length; i++) {
console.log(files[i]);
result.push({
fileName: files[i].name,
fileSize: files[i].size,
fileData: files[i],
state : "waiting",
taskId: Math.random().toString().substr(2)
});
}
self.uploadFiles = result;
self.onselect(result);
}
},
getFileUploadXHR: function () { //单例
if (!window.fileUploadXHR) {
fileUploadXHR = new XMLHttpRequest();
}
this.xhr = window.fileUploadXHR;
return fileUploadXHR;
},
getUploadUrl: function () { //获取上传地址
return this.agent.getUploadUrl();
},
getUploadFiles:function(){ //获取上传队列
return this.uploadFiles.concat(this.completeFiles);
},
upload: function () {//开始上传请求
this.uploadNextFile();
},
cancel:function(){ //取消上传
this.xhr.abort();
},
uploadNextFile: function () { //每个上传文件会触发
var fileInfo = this.uploadFiles.shift();
this.completeFiles.push(fileInfo); //存入已完成列表
this.currentFile = fileInfo;
if (fileInfo) {
var self = this;
var xhr = this.getFileUploadXHR(); xhr.upload.onabort = function (oEvent) { };
xhr.upload.onerror = function (oEvent) { self.onerror(oEvent); };
xhr.upload.onload = function (oEvent) { self.onload(oEvent); };
xhr.upload.onloadend = function (oEvent) { };
xhr.upload.onloadstart = function (oEvent) { };
xhr.upload.onprogress = function (oEvent) {
console.log(oEvent);
fileInfo.state = "uploading";
fileInfo.sendedSize = oEvent.position;
fileInfo.percent = Math.round((oEvent.position / oEvent.total) * 100);
self.onprogress(fileInfo);
};
//xhr.ontimeout = function(oEvent){This.ontimeout(oEvent);};
xhr.onreadystatechange = function (oEvent) {
if (xhr.readyState == 4) {
if (xhr.status == 200) {
var responseText = xhr.responseText;
self.oncomplete(fileInfo);
}
}
}; var url = this.getUploadUrl();
xhr.open("POST", url, true); //xhr.timeout = this.timeout; //timeout
function getFormData(fileInfo) {
var formData = new FormData();
formData.append("filedata", fileInfo.fileData);
return formData;
}
var fd = getFormData(fileInfo);
xhr.send(fd);
}
},
onclick: function () { },
onselect:function(files){
this.agent.onselect && this.agent.onselect(files);
},
onload:function(e){
},
onprogress: function (fileInfo) {
this.agent.onprogress && this.agent.onprogress(fileInfo);
},
oncomplete: function (fileInfo) {
fileInfo.state = "complete";
this.agent.oncomplete && this.agent.oncomplete(fileInfo);
this.uploadNextFile();
}
} resultObject.init();
return resultObject;
}
三、调用示例:
<html>
<head>
<script src="jquery-1.8.3.js"></script>
<script src="swfobject.js"></script>
<script src="upload.js"></script>
</head>
<body>
<div style="position:absolute">
</div>
<ul id="uploadList"></ul>
</body>
<script>
function updateUI(fileInfo) {
var ul = $("#uploadList");
switch (fileInfo.state) {
case "waiting":
ul.append("<li taskId='" + fileInfo.taskId + "'>" + fileInfo.fileName + "(等待上传...)</li>");
break;
case "uploading":
ul.find("li[taskId=" + fileInfo.taskId + "]").html(fileInfo.fileName + "(" + fileInfo.percent + "%)");
break;
case "complete":
ul.find("li[taskId=" + fileInfo.taskId + "]").html(fileInfo.fileName + "(完成)");
break;
}
} var fileUpload = new FileUpload({
container: document.getElementById("uploadBtn"),
//uploadType:"flash",
getUploadUrl: function () {
return "upload.ashx";
},
onselect: function (files) {
var self = this;
$(files).each(function (i, n) {
updateUI(n);
});
setTimeout(function () { //异步,等待onselect函数return后才能调用upload
self.upload();
}, 10);
},
onprogress: function (fileInfo) {
updateUI(fileInfo);
},
oncomplete: function (fileInfo, responseText) {
updateUI(fileInfo);
console.log(this.getUploadFiles());
}
});
</script>
</html>
四、结束语
以上源码仅提供上传组件化思路,实际应用中要考虑更多,比如:弱网络环境下需要分块上传,断点续传,异常情况下的日志上报等等。
以上源码非本人原创,代码来源于139邮箱前端团队内部分享。希望对大家有所帮助。
五、参考资料
Facade模式实现文件上传(Flash+HTML5)的更多相关文章
- WCF 使用Stream模式进行文件上传 --节选自Packt.Net.Framework.4.5.Expert.Programming.Cookbook
使用Stream上传文件 文件上传功能是web程序/服务上常用和必须的功能,WCF也不例外.在4.0版本之前,WCF仅仅提供了buffered模式上传文件.从4.0版本之后,WCF开始提供了Strea ...
- java实现文件上传--flash上传
1.http请求的头信息是“application/octet-stream”,request body 是二进制的flash图片流 2.把流中的信息读入到文件中 代码如下,代码分三个部分: ---- ...
- PHP fastcgi模式大文件上传500错误
最近在项目中中上传图片时,大约有300多K,结果报了个服务器错误,以前从未遇到过,错误的内容如下: mod_fcgid: www.111cn.net HTTP request length 13229 ...
- 文件上传之Html5 + jQuery上传、asp.net web api接收
HTML: <div> <label for="fileUpload"> 选择文件 </label> <br/> <input ...
- asp.net 文件上传 Uploadify HTML5 带进度条
参考的https://www.cnblogs.com/lvdabao/p/3452858.html这位,在此基础上略有修改: 1.根据Layer,将上传附件做成弹窗显示,引入frame弹窗,在项目当中 ...
- 可接受多个值的文件上传字段HTML5新特性
<input type="file" id="input" multiple="multiple"> 主要是多了个multip ...
- 强大的支持多文件上传的jQuery文件上传插件Uploadify
支持多文件上传的jQuery文件上传插件Uploadify,目前此插件有两种版本即Flash版本和HTML5版本,对于HTML5版本会比较好的支持手机浏览器,避免苹果手机Safari浏览器不支持Fla ...
- jQuery文件上传插件Uploadify(转)
一款基于flash的文件上传,有进度条和支持大文件上传,且可以多文件上传队列. 这款在flash的基础上增加了html5的支持,所以在移动端也可以使用. 由于官方提供的版本是flash免费,html5 ...
- TZ_06_SpringMVC_传统文件上传和SpringMVC文件上传方式
1.传统文件上传方式 <!-- 文件上传需要的jar --> <dependency> <groupId>commons-fileupload</groupI ...
随机推荐
- 【guava】字符串操作
一,Strings类 public void testStrings(){ Strings.isNullOrEmpty("");//返回true Strings.nullToEmp ...
- MySQL事务及事务隔离级别 锁机制
什么是事务? 当多个用户访问同一份数据时,一个用户在更改数据的过程中可能有其他用户同时发起更改请求,为保证数据库记录的更新从一个一致性状态更改为另一个一致性状态,这样的操作过程就是事务.事务具有的AC ...
- 在StoryBoard对UICollectionViewCell 进行Autolayout是遇到的Xcode6.01的BUG
使用Sb对UICollectionViewCell 的内容进行Autolayout约束时候,发现了一个Xcode6.01的BUG,就是你对UICollectionCell约束完了之后,在模拟器上现实的 ...
- P2050 [NOI2012]美食节(费用流)
P2050 [NOI2012]美食节 P2053 [SCOI2007]修车的加强版 因为数据较大,一次性把所有边都加完会T 于是我们每次只连需要的边跑费用流 就是开始先连所有厨师做倒数第1道菜 跑费用 ...
- Flask Web开发实战(入门、进阶与原理解析)
URL重定向 错误响应 > 如果你想手动返回错误响应,可以使用Flask提供的abort()函数. XML 上下文全局变量 [](https://img2018.cnblogs.com/blog ...
- Android 简单适配器(SimpleAdapter)
1.介绍 2.简单适配器的实现方法 3.XML文件 (1)主页面布局 <?xml version="1.0" encoding="utf-8"?> ...
- Luogu P1801 黑匣子_NOI导刊2010提高(06)
P1801 黑匣子_NOI导刊2010提高(06) 题目描述 Black Box是一种原始的数据库.它可以储存一个整数数组,还有一个特别的变量i.最开始的时候Black Box是空的.而i等于0.这个 ...
- 【KMP】【字符串】KMP字符串匹配算法 学习笔记
一.简介 KMP是由Knuth.Morris和Prat发明的字符串匹配算法,它的时间复杂度是均摊\(O(n+m)\).其实用Hash也可以做到线性,只不过Hash存在极其微小的难以避免的冲突. ...
- JS中||的某些用法
var a = 0 ||'sda';console.log(a);//sda var a = '' ||'sda';console.log(a);//sda
- Oracle分组函数之CUBE魅力
Oracle的CUBE与ROLLUP功能很相似,也是在数据统计分析领域的一把好手. 关于ROLLUP的查询统计功能请参考文章<Oracle分组函数之ROLLUP魅力>(http://www ...