今天采用jq写了一个上传文件组件。支持进度异步上传,同时还支持上传后的图片移动,支持默认图片、支持单张图片(如修改头像),我后台保存处理代码是用vb.net的ashx来写的。这个只支持图片上传,需要文件上传的话请自已用代码修改。
以下是上传的效果图
UploadFile.ashx文件代码
<%@ WebHandler Language="VB" Class="UploadFile" %>
Public Class UploadFile : Implements IHttpHandler
Public ReadOnly Property IsReusable() As Boolean Implements IHttpHandler.IsReusable
Get
Return False
End Get
End Property
Public Sub ProcessRequest(ByVal context As HttpContext) Implements IHttpHandler.ProcessRequest
Dim File As HttpPostedFile = context.Request.Files("FileData"), Path As String = AppPath & "\UpFile\Temp\"
With context.Response
If File.FileName = "" Then .Write("文件无效") : .End()
Dim FName As String() = File.FileName.Split(".")
If FName.Length <> 2 Then .Write("文件名错误") : .End()
If "gif|png|jpg|jpeg|".IndexOf(FName(1).ToLower & "|") < 0 Then .Write("文件格式错误") : .End()
If IO.Directory.Exists(Path) = False Then IO.Directory.CreateDirectory(Path) '文件夹是否存在,不存在而创建
Dim FileName As String = Format(Now, "yyMMdd") & "_" & NewGUID() & "." & FName(1)
FileName = "1.jpg"
' File.SaveAs(Path & FileName)
.Write("Yes|/UpFile/Temp/" & FileName) : .End()
End With
End Sub
End Class
UpLoadFile.js代码
/*二进制发送前进行转换,不然报错无法上传 1.2.2*/
if (!XMLHttpRequest.prototype.sendAsBinary) {
XMLHttpRequest.prototype.sendAsBinary = function (datastr) {
function byteValue(x) { return x.charCodeAt(0) & 0xff; }
var ords = Array.prototype.map.call(datastr, byteValue); var ui8a = new Uint8Array(ords); this.send(ui8a.buffer);
}
}
var MoveDiv, UpLoadInput //移动对象
var BeUpLoadFile = {
Config: {
multiple: 0,//单图上传
id: '',
DefaultValue: '', //默认图片
FileCount: 2,//总文件数量
FileNum: 0,//当前文件数量
Count: 0, //待上传队列数
},
open: function (input, o, callback) {
var that = this, Config = that.Config = $.extend(this.Config, o), FileDiv = $(input).parent();
if (input.attr('multiple')) {
Config.multiple = 1;
Config.FileCount = input.data('count');
}
Config.DefaultValue = input.data('value');
Config.id = UpLoadInput= input.attr('id')
FileDiv.append("<input type='hidden' name='I" + Config.id + "' id='I" + Config.id + "' value='' />")
input.attr('accept', 'image/*')
input.bind('change', function () {
if (this.files.length <= 0) { return }
if (Config.multiple == 0) { //单文件上传
FileDiv.find('.Error').remove();
$(this).before('<div class="Progress"><em>' + this.files[0].name + '</em></div>');
that.uploadFile(this.files[0], FileDiv)
} else {
for (var n = 0; n < this.files.length; n++) {
that.AddItem(this.files[n], FileDiv) //添加上传文件队列
}
that.UpFiles(FileDiv);
if (Config.FileNum >= Config.FileCount) { FileDiv.hide(); }//达到上传限制数量
}
});
var pics = Config.DefaultValue.split(",")
for (var i = 0; i < pics.length; i++) {
if (pics[i] != "") {
var FItem
if (Config.multiple == 0) { //单文件上传
FItem = $(input).parent();
} else {
FItem = $('<div class="Item" ><div class="Close"></div></div>')
}
FItem.append('<div class="Imgs"><img src="' + pics[i] + '" draggable="false" /></div>')
FItem.data('status', 1)//上传完成标记
FItem.data('src', pics[i]) //存储文件地址
FItem.uploading = false;
FItem.find('.Close').bind('click', function () {
that.RemoveItem($(this).parent())
});
FItem.data('Move', false)//是否正在移动
FItem.data('Pos', { x: 0, y: 0 }) //默认位置
FItem.data('Offset', { x: 0, y: 0 }) //默认位置
FItem.bind('mousedown', that.MouseDown)//绑定移动事件
FileDiv.before(FItem);
Config.FileNum += 1;
}
}
if (Config.multiple == 1) {
$(document).bind('mousemove', that.MouseMove)
$(document).bind('mouseup', that.MouseUp)
$('#I' + this.Config.id).val(Config.DefaultValue);//存储默认地址
if (Config.FileNum >= Config.FileCount) { FileDiv.hide(); }//达到上传限制数量
}
},
//开始上传单个文件
uploadFile: function (File, FileDiv) {
var that = this, Config = this.Config, xhr = File.xhr = new XMLHttpRequest();
File.uploading = true;//正在上传
if (typeof FormData === 'function' || typeof FormData === 'object') {
var formData = new FormData(); formData.append("FileData", File); xhr.open("post", "/Include/UploadFile.ashx", true);
xhr.upload.addEventListener('progress', function (e) { that.progress(e, FileDiv) }, false);
xhr.addEventListener('load', function (e) {
File.uploading = false; //上传结束
if (this.readyState == 4) {
if (this.status == 200) {
if (xhr.responseText.indexOf('Yes') >= 0) {
that.uploadComplete(e, xhr.responseText, FileDiv);
} else {
that.error(xhr.responseText, FileDiv);
}
} else if (this.status == 404) {
that.error("上传路径错误", FileDiv);
} else if (this.status == 403) {
that.error("无上传权限", FileDiv);
} else if (this.status == 500) {
that.error("文件太大", FileDiv);
} else {
that.error(this.status + "错误", FileDiv);
}
}
});
xhr.send(formData);
} else {
var reader = new FileReader();
reader.onload = function (e) {
var boundary = '-------------------------' + (new Date).getTime(), dashes = '--', eol = '\r\n', binFile = '';
binFile += dashes + boundary + eol;
binFile += 'Content-Disposition: form-data; name="FileData"';
if (File.name) { binFile += '; filename="' + File.name + '"' }
binFile += eol;
binFile += 'Content-Type: application/octet-stream' + eol + eol;
binFile += e.target.result + eol;
binFile += dashes + boundary + dashes + eol;
xhr.upload.addEventListener('progress', function (e) { that.progress(e, FileDiv) }, false);
xhr.addEventListener('load', function (e) {
File.uploading = false; //上传结束
if (this.status == 404) {
that.error("上传路径错误", FileDiv);
} else {
if (xhr.responseText.indexOf('Yes') >= 0) {
that.uploadComplete(e, xhr.responseText, FileDiv);
} else {
that.error(xhr.responseText, FileDiv);
}
}
}, false);
xhr.open("post", "/Include/UploadFile.ashx", true); xhr.setRequestHeader("Content-Type", "multipart/form-data; boundary=" + boundary); xhr.sendAsBinary(binFile);
}
reader.readAsBinaryString(File);
}
delete xhr;
},
//单个文件取消上传,发出拔出请求
cancel: function (FileItem) {
if (FileItem.uploading) {
FileItem.uploading = false;
FileItem.xhr.abort();
delete FileItem.xhr;
}
},
//单个文件上传错误
error: function (msg, FileDiv) {
FileDiv.find('.Progress').remove();
FileDiv.append('<div class="Error">' + msg + '</div>')
},
//显示单个文件上传进度
progress: function (e, FileDiv) {
if (e.lengthComputable) {
var percent = Math.round((e.loaded / e.total) * 100);
FileDiv.find('.Progress em').html(percent + '%')
}
},
//单个文件上传完成
uploadComplete: function (e, responseText, FileDiv) {
var that = this, Config = this.Config
FileDiv.find('.Progress').remove();
FileDiv.find('.Imgs').remove();
FileDiv.append('<div class="Imgs"><img src="' + responseText.split("|")[1] + '"/></div>')
FileDiv.data('status', 1)//上传完成标记
FileDiv.data('src', responseText.split("|")[1]) //存储文件地址
if (Config.multiple == 0) {//单文件上传
FileDiv.find('#I' + Config.id).val(responseText.split("|")[1]);//更新存储地址
} else {
Config.Count -= 1;
if (Config.Count <= 0) {
that.ImgChange();//更新存储地址
}
}
},
//添加到队列
AddItem: function (File, FileDiv) {
var that = this;
if (this.Config.FileNum >= this.Config.FileCount) { return }//超出限制数量
File.Item = $('<div class="Item"><div class="Close"></div><div class="Progress"><em>' + File.name + '</em></div></div>')
File.Item.data('File', File);
File.Item.data('status', 0);//是否已经上传
File.Item.find('.Close').bind('click', function () {
that.RemoveItem(File.Item)
});
File.Item.data('Move', false)//是否正在移动
File.Item.data('Pos', { x: 0, y: 0 }) //默认位置
File.Item.data('Offset', { x: 0, y: 0 }) //默认位置
File.Item.bind('mousedown', that.MouseDown)//绑定移动事件
FileDiv.before(File.Item);
this.Config.FileNum += 1; this.Config.Count += 1;
},
//移出队列
RemoveItem: function (FileItem) {
var Config = this.Config
this.cancel(FileItem)
if (FileItem.data('status') == 0) { Config.Count -= 1; }
Config.FileNum -= 1;
if (Config.FileNum < Config.FileCount) {
FileItem.parent().find('.on').show();//未达上传限制数量
}
FileItem.remove();
delete FileItem;
this.ImgChange();
},
//批量依次上传
UpFiles: function (FileDiv) {
var that = this;
FileDiv.parent().find('.Item').each(function () {
var Item = $(this)
if (Item.data('status') == '0') {
that.uploadFile(Item.data('File'), Item)
}
});
},
//更新保存图片地址
ImgChange: function () {
var Imgs='';
$('#' + UpLoadInput).parent().parent().find('.Item').each(function () {
if ($(this).data('src')) {
Imgs += $(this).data('src') + ',';
}
});
if (Imgs != "") { Imgs = Imgs.substring(0, Imgs.length - 1) }
$('#I' + UpLoadInput).val(Imgs);
},
//移动图像按下
MouseDown: function (event) {
var Div = MoveDiv = $(this), Pos = Div.data('Pos'), Offset = Div.data('Offset') //拖拽对象
Div.data('Move', true); Div.css("z-index", 9999);
Pos.x = Div.offset().left;//对象在屏幕位置
Pos.y = Div.offset().top;
Offset.x = event.pageX - Div.offset().left;//鼠标在对象上的偏位位置,还原需要负数
Offset.y = event.pageY - Div.offset().top;
},
//移动图像位置
MouseMove: function (event) {
if (!MoveDiv) { return }
if (!MoveDiv.data('Move')) { return }
var Pos = MoveDiv.data('Pos'), Offset = MoveDiv.data('Offset')
var NewPos = { x: 0, y: 0 }
NewPos.x = event.pageX - Pos.x - Offset.x;//鼠标在对象上的偏位位置,还原需要负数
NewPos.y = event.pageY - Pos.y - Offset.y;
MoveDiv.css({ left: NewPos.x + 'px', top: NewPos.y + 'px' });
},
//移动图像松开
MouseUp: function (event) {
if (!MoveDiv) { return }
MoveDiv.data('Move', false); MoveDiv.css("z-index", 0);
var Pos = MoveDiv.data('Pos'), NewPos = { x: MoveDiv.offset().left - Pos.x, y: MoveDiv.offset().top - Pos.y }, Mode=0,end=0, w = MoveDiv.width() /2, h = MoveDiv.height() / 2
if (NewPos.x < 0 && NewPos.y < 0) {//前上
Mode = 1
} else if (NewPos.x < 0 && NewPos.y > 0) {//前下
Mode = 2
end=0
} else if (NewPos.x > 0 && NewPos.y < 0) { //后上
Mode = 3
} else if (NewPos.x > 0 && NewPos.y > 0) {//后下
Mode = 4
end=0
}
NewPos = { x: MoveDiv.offset().left, y: MoveDiv.offset().top }
MoveDiv.parent().find('.Item:not(.on)').each(function () {
var ItemPos = { x: $(this).offset().left, y: $(this).offset().top }
if (Mode == 1 || Mode == 3) {
if (ItemPos.x > NewPos.x - w && ItemPos.y > NewPos.y - h) {
$(this).before(MoveDiv)
return false;
}
} else if (Mode == 2 || Mode == 4) {
if (ItemPos.x > NewPos.x - w && ItemPos.y > NewPos.y - h) {
if (end > 0) {
$(this).after(MoveDiv)
return false;
}
end += 1
}
}
});
MoveDiv.css({ left: '0px', top: '0px' });//对齐处理
BeUpLoadFile.ImgChange()
}
};
$.fn.UpLoadFile = function () {
BeUpLoadFile.open(this)
}
CSS代码,单张图片上传与多张上传是分开的。
/* 上传单张图片CSS */
.UpImg .Imgs img {
max-width: 100%;
max-height: 100%;
}
.UpImg .Error {
width: 100%;
z-index: 1;
text-align: center;
color: #e90908;
position: absolute;
bottom: 0px;
}
.UpImg .Progress {
width: 100%;
height: 100%;
z-index: 1;
background: url("/Images/loader.gif") no-repeat center #fff;
}
.UpImg .Progress em {
width: 100%;
position: absolute;
text-align: center;
bottom: 0px;
font-family: Arial;
}
/* 上传多张图片CSS */
.UpImgs .Item {
width: 100px;
height: 100px;
margin-right: 10px;
margin-top: 10px;
float: left;
border: solid 1px #eee;
position: relative;
background:#efefef;
}
.UpImgs .Item.on {
border: solid 1px #efefef;
background: url("/Images/UpImgView.gif") no-repeat center #f6f6f6;
}
.UpImgs .Item:hover {
border: dashed 1px #f00;
}
.UpImgs .Item img {
max-width: 100%;
max-height: 100%;
}
.UpImgs .Close {
background: url("/Images/UPic_Del.png");
width: 16px;
height: 16px;
position: absolute;
z-index:2;
right:0px;
margin-top:-8px;
margin-right:-8px;
cursor:pointer;
}
.UpImgs .Error {
width: 100%;
z-index: 1;
text-align: center;
color: #f00;
position: absolute;
top: 50%;
margin-top: -14px;
}
.UpImgs .Progress {
width: 100%;
height: 100%;
z-index: 1;
background: url("/Images/loader.gif") no-repeat center ;
}
.UpImgs .Progress em {
width: 100%;
position: absolute;
text-align: center;
bottom: 0px;
font-family: Arial;
}
页面html代码
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
<title>JS上传方件组件</title>
<meta name="description" content="">
<meta name="keywords" content="">
<meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1" />
<meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">
<link href="/Global.css" rel="stylesheet" type="text/css" media="all" />
<script src="/Include/jquery.js" charset="utf-8" type="text/javascript"></script>
<script src="/Include/UpLoadFile.js" charset="utf-8" type="text/javascript"></script>
</head>
<body>
<div class="PageTitle">
上传文件
</div>
<div class=" UpImgs" style="margin-top:20px;">
<div class="Item on">
<input id="Picture" name="Picture" type="file" multiple="multiple" data-count="100" data-value="/UpFile/Temp/1.jpg,/UpFile/Temp/2.jpg,/UpFile/Temp/3.jpg,/UpFile/Temp/4.jpg,/UpFile/Temp/5.jpg,/UpFile/Temp/6.jpg,/UpFile/Temp/7.jpg,/UpFile/Temp/8.jpg,/UpFile/Temp/9.jpg,/UpFile/Temp/10.jpg,/UpFile/Temp/11.jpg,/UpFile/Temp/12.jpg,/UpFile/Temp/13.jpg,/UpFile/Temp/14.jpg,/UpFile/Temp/15.jpg,/UpFile/Temp/16.jpg" />
</div>
</div>
<script type="text/javascript">
// capture='camera'
$("#Picture").UpLoadFile()
</script>
</body>
</html>