NET自带的上传控件有点磕碜。Jquery确实是个好东西。所有后端语言都能使用。
最近了解了下一款国外的Jquery上传控件Plupload ,界面挺美观。扩展性也很强大。
记忆力不好,记录一下使用的心得,以备以后使用。
Plupload官网:http://www.plupload.com/
插件下载地址:http://www.plupload.com/download
插件演示:http://www.plupload.com/examples/
插件文档:http://www.plupload.com/docs/
插件语言包:http://www.plupload.com/i18n/ (支持中文)
Plupload支持分块上传(用于大文件上传)。通过后端代码就可以了解到什么是分块上传。
就是例如1个100M的文件。分成25块。每块4M。每次上传4M到服务器上。总共上传25次。保存文件采用append(附加)形式。把25次上传的文件块附加到一个文件中,得到一个完整的100M文件。
支持多文件上传。而且还支持过滤器。
除IE6不怎么兼容外,兼容主流各版本浏览器。
支持的Event事件:
具体请看演示:http://www.plupload.com/examples/events
Refresh: function(up) {
// Called when upload shim is moved
},
StateChanged: function(up) {
// Called when the state of the queue is changed
},
QueueChanged: function(up) {
// Called when the files in queue are changed by adding/removing files
},
UploadProgress: function(up, file) {
// Called while a file is being uploaded
},
FilesAdded: function(up, files) {
// Callced when files are added to queue
},
FilesRemoved: function(up, files) {
// Called when files where removed from queue
},
FileUploaded: function(up, file, info) {
// Called when a file has finished uploading
},
ChunkUploaded: function(up, file, info) {
// Called when a file chunk has finished uploading
},
Error: function(up, args) {
// Called when a error has occured
}
简单的实例:
前端:
JS/CSS引用:
<link href="../Scripts/upload/jquery.plupload.queue/css/jquery.plupload.queue.css" rel="stylesheet" />
<script src="../Scripts/jquery-1.10.2.min.js"></script>
<script src="../Scripts/upload/plupload.full.min.js"></script>
<script src="../Scripts/upload/jquery.plupload.queue/jquery.plupload.queue.min.js"></script>
//引用中文语言包
<script src="../Scripts/upload/i18n/zh_CN.js"></script>
前端JS代码:
<script type="text/javascript">
// Initialize the widget when the DOM is ready
$(function () {
// Setup html5 version
$("#uploader").pluploadQueue({
// General settings
runtimes: 'html5,flash,silverlight,html4',
url: "../API/upload.ashx", //后端交互处理地址
chunk_size: '1mb', //分块大小
rename: true, //重命名
dragdrop: true, //允许拖拽文件进行上传
filters: { //过滤器
max_file_size: '10mb', //文件最大尺寸
mime_types: [ //允许上传的文件类型
{ title: "Image", extensions: "jpg,gif,png" },
{ title: "Rar", extensions: "zip,rar" }
]
},
//自定义参数 (键值对形式) 此处可以定义参数
multipart_params: {
type:"misoft"
},
// 生成缩略图的定义(如果满足生成条件)
resize: {
width: 200,
height: 200,
quality: 90,
crop: true // crop to exact dimensions
},
// FLASH的配置
flash_swf_url: '../Scripts/upload/Moxie.swf',
// Silverligh的配置
silverlight_xap_url: '../Scripts/upload/Moxie.xap'
});
});
</script>
前端HTML代码:
<div id="fileQueue"></div>
<div id="uploader">
<p>你的浏览器不支持 Flash, Silverlight 或 HTML5 .</p>
</div>
后端upload.ashx处理代码:
public void ProcessRequest(HttpContext context)
{
int chunk = context.Request.Params["chunk"] != null ? int.Parse(context.Request.Params["chunk"]) : 0; //获取当前的块ID,如果不是分块上传的。chunk则为0
string fileName = context.Request.Params["name"] != null ? context.Request.Params["name"] : "1.jpg"; //这里写的比较潦草。判断文件名是否为空。
string type= context.Request.Params["type"]; //在前面JS中不是定义了自定义参数multipart_params的值么。其中有个值是type:"misoft",此处就可以获取到这个值了。获取到的type="misoft";
//对文件流进行存储 需要注意的是 files目录必须存在(此处可以做个判断) 根据上面的chunk来判断是块上传还是普通上传 上传方式不一样 ,导致的保存方式也会不一样
FileStream fs = new FileStream(System.Web.HttpContext.Current.Server.MapPath("../files/" + fileName), chunk == 0 ? FileMode.OpenOrCreate : FileMode.Append);
//write our input stream to a buffer
Byte[] buffer = null;
if (context.Request.ContentType == "application/octet-stream" && context.Request.ContentLength > 0)
{
buffer = new Byte[context.Request.InputStream.Length];
context.Request.InputStream.Read(buffer, 0, buffer.Length);
}
else if (context.Request.ContentType.Contains("multipart/form-data") && context.Request.Files.Count > 0 && context.Request.Files[0].ContentLength > 0)
{
buffer = new Byte[context.Request.Files[0].InputStream.Length];
context.Request.Files[0].InputStream.Read(buffer, 0, buffer.Length);
}
//write the buffer to a file.
fs.Write(buffer, 0, buffer.Length);
fs.Close();
context.Response.Write("上传成功!");
}
一个网站的不安全很大程度问题都出了在上传上。
试想一下,正常人上传的是JPG。如果我是个骇客。我上传个ASPX文件上去。后果会有多严重就不用多说了。
任何JS的验证只能视为辅助验证。其验证的结果对于后端来说都是不可信的。
所以关键地方,一定要用后端进行二次验证。
后端验证方式有很多。比如验证后缀。这种方式依旧不安全。
推荐验证字节流。
这里有两种方式可以验证。
protected bool isValidImage(System.Web.HttpPostedFile postedFile)
{
string sMimeType = postedFile.ContentType.ToLower();
if (sMimeType.IndexOf("image/") < 0)
return false;
if (postedFile.ContentLength < 50)
return false;
try
{
System.Drawing.Image img = System.Drawing.Image.FromStream(postedFile.InputStream);
if (img.Width * img.Height < 1)
return false;
img.Dispose();
}
catch
{
return false;
}
return true;
}
//真正是否真的为图片
public static bool IsAllowedExtension(FileUpload hifile)
{
FileStream fs = new FileStream(hifile.PostedFile.FileName,FileMode.Open,FileAccess.Read);
BinaryReader r = new BinaryReader(fs);
string fileclass = "";
byte buffer;
try
{
buffer = r.ReadByte();
fileclass = buffer.ToString();
buffer = r.ReadByte();
fileclass += buffer.ToString();
}
catch { }
r.Close();
fs.Close();
//说明255216是jpg;7173是gif;6677是BMP,13780是PNG;7790是exe,8297是rar,|| fileclass=="13780"||fileclass=="6677"
if (fileclass == "255216" || fileclass == "7173")
{
return true;
}
else
{
return false;
}
}
这2种方式对图片是否为真实图片的验证基本万无一失了。