今天晚上花了几个小时的功夫做了一个相册,类似于QQ空间的文件上传,不过我用的Ext+HTML5等新的技术,结合Servlet上传文件。有几个特点:
- 文件拖拽上传
- 实时获取上传进度
- 本地预览
- 与Ext结合起来
说了这么多,还是贴几张图给大家吧!!
这个是没有做任何操作时候的窗口
拖动图片的时候,提示将图片拖动到指定的区域
这个是拖拽进去后,生成了本地预览,并有相应的详细信息
这个是上传成功后显示的信息。这里可能是本地的原因,一下子就上传完了,没有体现出百分比来。大概就是这个样子了!下面说下实现:
首先构建Ext窗口:
//创建相册窗口
var win = Ext.create('Ext.window.Window', {
title : 'Ext相册',
width : 700,
height : 400,
iconCls : 'ablum',
layout : 'fit',
plain : false,
items : [view],
buttons : [{
text : '上传', //上传按钮
handler : upload,
iconCls : 'upload'
}, {
text : '清空',
handler : function() {
store.removeAll();
},
iconCls : 'clear'
}]
});
win.show();
创建像是图片的容器:
//创建图片数据模型 ,数据源需要
var PhotoModel = Ext.define('ImageModel', {
extend : 'Ext.data.Model',
fields : [{name : 'name'},
{name : 'type'},
{name : 'size', type : 'float'},
{name : 'lastmod', type : 'date',dateFormat : 'timestamp'},
{name : 'file'},
{name : 'src'}]
});
//创建数据源
var store = Ext.create("Ext.data.Store", {
model : PhotoModel
});
var ddtip;
//图片提示模板
var tiptpl = '名 称:{0}<br/>' +
'类 型:{1}<br/>' +
'大 小:{2}<br/>' +
'修改时间:{3}<br/>'
//创建图片存放的容器
var view = Ext.create('Ext.view.View', {
store : store, //指定数据源
tpl : [ //设置展示模板
'<tpl for=".">',
'<div class="thumb-wrap" id="{name}">',
'<div class="upload-progress">0%</div>',
'<div class="thumb"><img src="{src}"></div>',
'<span>{name}</span></div>', '</tpl>',
'<div class="x-clear"></div>'],
style : {
backgroundColor : '#FFFFFF',
fontFamily : '微软雅黑'
},
multiSelect : true,
trackOver : true,
overItemCls : 'x-item-over',
itemSelector : 'div.thumb-wrap',
emptyText : '没有显示的相片',
autoScroll : true,
listeners : {
'afterrender' : function() {
//创建用户拖拽提示
ddtip = view.el.createChild({
tag : 'div',
cls : 'dd-tip',
html : '请将图片拖动到这里'
});
//创建相片浮动提示
Ext.create('Ext.tip.ToolTip', {
target : view.el,
delegate : view.itemSelector,
trackMouse : true,
renderTo : Ext.getBody(),
anchor : 'right',
listeners : {
beforeshow : function(tip) {
var record = view
.getRecord(tip.triggerElement);
tip.update(Ext.String.format(
tiptpl, record
.get('name'),
record.get('type'), record
.get('size'),
Ext.Date.format(
record.get('lastmod'),
'Y年m月d日 H时i分')));
}
}
});
}
}
});
添加监听页面拖拽事件:
//给body添加事件,如果有拖拽的话提示用户拖拽到指定区域
Ext.getBody().on('dragover', function(e) {
ddtip.show();
});
//当用户拖拽离开时隐藏提示信息
Ext.getBody().on('dragleave', function(e) {
ddtip.hide();
});
//当用户拖拽到指定区域时,隐藏提示信息
view.el.on('dragenter', function(e) {
e.stopPropagation();
e.preventDefault();
ddtip.hide();
view.el.highlight();
});
//当用户拖拽离开指定区域时显示提示信息
view.el.on('dragleave', function(e) {
e.stopPropagation();
e.preventDefault();
ddtip.show();
});
//很关键!!当用户拖拽文件并放下的时候触发时间
view.el.dom.ondrop = function(e) {
e.stopPropagation();
e.preventDefault();
ddtip.hide();//隐藏提示信息
//处理用户拖拽过来的文件
process(e.dataTransfer.files);
};
处理用户拖拽过来的文件:
function process(files) {
var count = 0;
for (var i = 0; i < files.length; i++) {
var file = files[i];//这个一个File对象
//创建一个相片数据实例,保存名称,大小,类型,修改日期,文件等信息
var photo = Ext.ModelManager.create({
name : file.fileName,
size : file.fileSize,
type : file.type,
file : file,
lastmod : file.lastModifiedDate
}, PhotoModel);
//添加到数据源中,这时候容易会发生相应的变化
store.add(photo);
//通过FileReader对象获取预览
var reader = new FileReader();
//当读取完成之后执行的回调
reader.onload = (function(p) {
return function() {
count++;
//将获取到的Base64格式的图片数据,存放起来
p.data.src = this.result;
if (count == files.length) {
//当所有图片都加载完了之后,渲染图片
view.refresh();
}
}
})(photo);//这个地方利用了JS的闭包原理
//读取图片
reader.readAsDataURL(file);
}
}
处理上传方法:
function upload(){ //执行上传
store.each(function(photo){//遍历数据源的数据
var progress = Ext.get(view.getNode(photo)).down('div.upload-progress');//显示进度信息
progress.show();
var xhr = new XMLHttpRequest(); //初始化XMLHttpRequest
xhr.open('post', 'upload', true);
xhr.upload.onprogress = function(p) { //添加数据上传进度,获取实时的上传进度
return function(e) {
if (e.lengthComputable) {
var percentage = Math.round((e.loaded * 100) / e.total);
progress.update(percentage + "%");
}
}
}(progress);
xhr.upload.onload = function(p) { //当上传完之后执行的回调函数
return function(e) {
progress.update("上传成功!");
}
}(progress);
var fd = new FormData(); //这里很关键,初始化一个FormData,并将File文件发送到后台
fd.append("file", photo.data.file);
xhr.send(fd);
});
}
Servlet实现文件上传的代码:
@SuppressWarnings("unchecked")
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String path = request.getSession().getServletContext().getRealPath("\\upload");
DiskFileItemFactory factory = new DiskFileItemFactory();
ServletFileUpload upload = new ServletFileUpload(factory);
try {
List<FileItem> list = (List<FileItem>) upload.parseRequest(request);
for (FileItem fileItem : list) {
String fileName = fileItem.getName();
File file = new File(path + "\\" + fileName);
fileItem.write(file);
fileItem.delete();
}
} catch (Exception e) {
e.printStackTrace();
}
}
就这样,这个相册实例就完成了
!
------------------------------------------------------------------------------分割线---------------------------------------------------------------------------------
2012-05-14更新:
- 增加了通过资源管理器选择文件功能
- 修复上传进度显示BUG
- 增加相片右键菜单
- 上传更改为上传全部项和上传选中项
- 增加图片浏览器功能
- 图片浏览器支持拖动、双击最大化/还原、更改尺寸
- 图片浏览器支持对数据源里面的图片进行导航
- 图片浏览器图片的放大和缩小
由于更新的比较仓促,写的代码质量不是很高,应该将图片浏览器封装成一个对象,并且图片旋转的功能没有完成。这些工作就留给大家伙自己实现吧,图片旋转的代码网上都有。贴图给大家:
通过点击添加按钮选取文件
相片右键菜单
图片查看器,双击相片可以启动。支持图片放大,导航!
确定只能在chrome下运行,在firefox下运行有错,不是不能调,只是懒得调了!
源码等会会放到下载区里面,只是优快云有延迟,找不到链接!
---------------------------------------------------------------------------------------------分割线-------------------------------------------------------------------------------------------
大家测试最好用最新版的Google Chrome浏览器。
在chrome下运行有效,firefox还在测试,IE忽略不计!!讨厌IE!!
最后打下小广告,
看文章评论一下是美德,你的评论是我最大的动力!!