-
大文件上传部分:重磅功能:大文件“秒传”;在文件上传部分已有功能的基础上实现了按10MB分为多个块,异步上传,服务端合并,MD5验证;
-
图片上传部分:在文件上传部分已有功能的基础上实现了上传前缩略图预览,前台js文件后缀验证,后台代码文件后缀验证和文件类型验证(就算修改后缀名也无法成功上传),支持图片上传前压缩;
BigFileUpload文件夹下Index.cshtml
@{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<title>大文件上传</title>
<!--支持IE9+ chrome fireFox-->
<script src="~/Scripts/jquery-2.1.4.min.js"></script>
<link href="~/Content/webuploader.css" rel="stylesheet"/>
<script src="~/Scripts/webuploader.nolog.js"></script>
<link href="~/Content/bootstrap.min.css" rel="stylesheet"/>
<script src="~/Scripts/bootstrap.min.js"></script>
<script type="text/javascript">
$(function() {
$list = $('#fileList');
var uploader = WebUploader.create({
//设置选完文件后是否自动上传
auto: false,
//swf文件路径
//swf: BASE_URL + '~/FileUpload/Uploader.swf',
swf: '../FileUpload/Uploader.swf',
// 文件接收服务端。
server: '/BigFileUpload/BigFileUp',
// 选择文件的按钮。可选。
// 内部根据当前运行是创建,可能是input元素,也可能是flash.
pick: '#picker',
chunked: true, //开启分块上传
chunkSize: 10 * 1024 * 1024,
chunkRetry: 3, //网络问题上传失败后重试次数
threads: 5, //上传并发数
//formData: { guid: WebUploader.guid() }, //一个文件有一个guid,在服务器端合并成一个文件 这里有个问题,多个文件或者上传一个文件成功后不刷新直接添加文件上传生成的guid不变!!! 暂时只能传一个大文件(已解决)
//fileNumLimit :1,
fileSizeLimit: 2000 * 1024 * 1024, //最大2GB
fileSingleSizeLImit: 2000 * 1024 * 1024,
resize: false //不压缩
//选择文件类型
//accept: {
// title: 'Images',
// extensions: 'gif,jpg,jpeg,bmp,png',
// mimeTypes: 'image/*'
//}
});
// 当有文件被添加进队列的时候
uploader.on('fileQueued',
function(file) {
$list.append('<div id="' +
file.id +
'" class="item">' +
'<h4 class="info">' +
file.name +
'<button type="button" fileId="' +
file.id +
'" class="btn btn-danger btn-delete"><span class="glyphicon glyphicon-trash"></span></button></h4>' +
'<p class="state">等待上传...</p>' +
'</div>'); //id="' + file.id + 'btn"
//删除要上传的文件
//每次添加文件都给btn-delete绑定删除方法
$(".btn-delete").click(function() {
//console.log($(this).attr("fileId"));//拿到文件id
uploader.removeFile(uploader.getFile($(this).attr("fileId"), true));
$(this).parent().parent().fadeOut(); //视觉上消失了
$(this).parent().parent().remove(); //DOM上删除了
});
uploader.options.formData.guid = WebUploader.guid(); //每个文件都附带一个guid,以在服务端确定哪些文件块本来是一个
uploader.md5File(file)
.then(function(fileMd5) { // 完成
//var end = +new Date();
// console.log("before-send-file preupload: file.size="+file.size+" file.md5="+fileMd5);
//insertLog("<br>" + moment().format("YYYY-MM-DD HH:mm:ss") + " before-send-file preupload:计算文件(" + file.name + ")MD5完成. 耗时 " + (end - start) + '毫秒 fileMd5: ' + fileMd5);
file.wholeMd5 = fileMd5; //获取到了md5
uploader.options.formData.md5value = file.wholeMd5; //每个文件都附带一个md5,便于实现秒传
$.ajax({ //向服务端发送请求
cache: false,
type: "post",
dataType: "json",
url: "/BigFileUpload/IsMD5Exist", //baseUrl +
data: {
fileMd5: fileMd5,
fileName: file.name,
fileID: file.id,
//isShared: $("#isShared").val()
},
success: function(result) {
console.log(result);
if (result == "this file is exist") {
console.log("服务器上已经有同样的文件了,开始秒传!");
uploader.removeFile(file, true);
$('#' + file.id).find('p.state').text('已上传');
$('#' + file.id).find(".progress").find(".progress-bar")
.attr("class", "progress-bar progress-bar-success");
$('#' + file.id).find(".info").find('.btn').fadeOut('slow'); //上传完后删除"删除"按钮
} else {
console.log("服务器上没有同样的文件,秒传失败!");
}
//$('#uploadBtn').attr("disabled", false);
//me.options.formData.fileMd5 = fileMd5;
//me.options.formData.isShared = $("#isShared").val();
//me.options.formData.fileType = $("#fileType").val();
//if (result.result) {//文件存在
// insertLog("<br>" + moment().format("YYYY-MM-DD HH:mm:ss") + " before-send-file preupload:文件 " + file.name + " 已经存在,跳过上传 fileMd5:" + fileMd5);
// $MD5Percent.hide();
// var $li = $('#' + file.id),
// $percent = $li.find('.progress .progress-bar-success');
// $li.find('span.state').text('文件重复,已跳过');
// $percent.css('width', 100 + '%');
// owner.skipFile(file);
//} else {//文件不存在
// file.wholeMd5 = fileMd5;
// file.chunkMd5s = result.chunkMd5s; //如果后台已经有该文件的分片记录
//}
me.data.chunksMd5 = "chunksMd5";
//$('#' + file.id + ' .cancleBtn').removeClass("btn-info");
//$('#' + file.id + ' .cancleBtn').attr("disabled", true);
//deferred.resolve(true);
return deferred.reject();
}
});
});
});
// 文件上传过程中创建进度条实时显示。
uploader.on('uploadProgress',
function(file, percentage) {
var $li = $('#' + file.id),
$percent = $li.find('.progress .progress-bar');
// 避免重复创建
if (!$percent.length) {
$percent = $('<div class="progress progress-striped active">' +
'<div class="progress-bar" role="progressbar" style="width: 0%">' +
'</div>' +
'</div>').appendTo($li).find('.progress-bar');
}
$li.find('p.state').text('上传中');
$percent.css('width', percentage * 100 + '%');
});
给每个文件一个唯一的guid值
//uploader.on('uploadBeforeSend', function (block, data) {
// // block为分块数据。
// // file为分块对应的file对象。
// //var file = block.file;
// // 修改data可以控制发送哪些携带数据。
// //data.uid = 123;
// // 将存在file对象中的md5数据携带发送过去。
// // data.fileMd5 = file.md5;
// // 删除其他数据
// // delete data.key;
//});
uploader.on('uploadSuccess',
function(file) {
$('#' + file.id).find('p.state').text('已上传');
$('#' + file.id).find(".progress").find(".progress-bar")
.attr("class", "progress-bar progress-bar-success");
$('#' + file.id).find(".info").find('.btn').fadeOut('slow'); //上传完后删除"删除"按钮
});
uploader.on('uploadError',
function(file) {
$('#' + file.id).find('p.state').text('上传出错');
//上传出错后进度条爆红
$('#' + file.id).find(".progress").find(".progress-bar")
.attr("class", "progress-bar progress-bar-danger");
//添加重试按钮
//为了防止重复添加重试按钮,做一个判断
//var retrybutton = $('#' + file.id).find(".btn-retry");
//$('#' + file.id)
if ($('#' + file.id).find(".btn-retry").length < 1) {
var btn = $('<button type="button" fileid="' +
file.id +
'" class="btn btn-success btn-retry"><span class="glyphicon glyphicon-refresh"></span></button>');
$('#' + file.id).find(".info").append(btn); //.find(".btn-danger")
}
$(".btn-retry").click(function() {
//console.log($(this).attr("fileId"));//拿到文件id
uploader.retry(uploader.getFile($(this).attr("fileId")));
});
});
uploader.on('uploadComplete',
function(file) { //上传完成后回调
//$('#' + file.id).find('.progress').fadeOut();//上传完删除进度条
//$('#' + file.id + 'btn').fadeOut('slow')//上传完后删除"删除"按钮
});
uploader.on('uploadFinished',
function() {
//上传完后的回调方法
//alert("所有文件上传完毕");
//提交表单
});
$("#UploadBtn").click(function() {
uploader.upload(); //上传
});
$("#StopBtn").click(function() {
//uploader.upload();//上传
uploader.stop(true); //暂停上传有问题,这个变成了终止上传,开始之后就是完全重新上传了
});
uploader.on('uploadAccept',
function(file, response) {
//if (uploader.errorCode) {
// // 通过return false来告诉组件,此文件上传有错。
// return false;
//}
if (response._raw == '{"error":true}') {
return false;
}
});
// 扩展md5逻辑
//var uploader = WebUploader.Uploader;
/**
* method:before-send-file
* 在文件发送之前request,此时还没有分片(如果配置了分片的话),可以用来做文件整体md5验证。
* para:file: File对象
*/
//uploader.register({
// 'before-send-file': 'preupload'
//}, {
// preupload: function (file) {
// $('#UploadBtn').attr("disabled", true);
// var me = this,
// owner = this.owner,
// server = me.options.server,
// deferred = WebUploader.Deferred(),
// blob = file.source.getSource();
// //var fileMd5 = file.wholeMd5;
// var start = +new Date();
// var $li = $('#' + file.id),
// $MD5Percent = $li.find('.progress .progress-bar-info');
// $li.find('span.state').text('计算MD5');
// insertLog("<br>" + moment().format("YYYY-MM-DD HH:mm:ss") + " before-send-file preupload:开始计算文件(" + file.name + ")MD5. ");
// owner.md5File(file)
// .progress(function (percentage) { // 及时显示进度
// var percent = parseInt(percentage * 100) + '%';
// $MD5Percent.css('width', percent);
// $MD5Percent.html(percent);
// //console.log('Percentage:', percent);
// })
// .then(function (fileMd5) { // 完成
// var end = +new Date();
// // console.log("before-send-file preupload: file.size="+file.size+" file.md5="+fileMd5);
// insertLog("<br>" + moment().format("YYYY-MM-DD HH:mm:ss") + " before-send-file preupload:计算文件(" + file.name + ")MD5完成. 耗时 " + (end - start) + '毫秒 fileMd5: ' + fileMd5);
// file.wholeMd5 = fileMd5;
// $.ajax({
// cache: false,
// type: "post",
// dataType: "json",
// url: baseUrl + "/fileUpload/existsMd5",
// data: {
// fileMd5: fileMd5,
// fileName: file.name,
// isShared: $("#isShared").val()
// },
// success: function (result) {
// $('#uploadBtn').attr("disabled", false);
// me.options.formData.fileMd5 = fileMd5;
// me.options.formData.isShared = $("#isShared").val();
// me.options.formData.fileType = $("#fileType").val();
// if (result.result) {//文件存在
// insertLog("<br>" + moment().format("YYYY-MM-DD HH:mm:ss") + " before-send-file preupload:文件 " + file.name + " 已经存在,跳过上传 fileMd5:" + fileMd5);
// $MD5Percent.hide();
// var $li = $('#' + file.id),
// $percent = $li.find('.progress .progress-bar-success');
// $li.find('span.state').text('文件重复,已跳过');
// $percent.css('width', 100 + '%');
// owner.skipFile(file);
// } else {//文件不存在
// file.wholeMd5 = fileMd5;
// file.chunkMd5s = result.chunkMd5s; //如果后台已经有该文件的分片记录
// }
// // me.data.chunksMd5 = "chunksMd5";
// $('#' + file.id + ' .cancleBtn').removeClass("btn-info");
// $('#' + file.id + ' .cancleBtn').attr("disabled", true);
// deferred.resolve(true);
// // return deferred.reject();
// }
// });
// });
// return deferred.promise();
// }
//});
});
</script>
</head>
<body>
<div class="container" style="margin-top: 20px">
<div class="alert alert-info">可以一次上传多个大文件</div>
</div>
<div class="container" style="margin-top: 50px">
<div id="uploader" class="container">
<div class="container">
<div id="fileList" class="uploader-list"></div> <!--存放文件的容器-->
</div>
<div class="btns container">
<div id="picker" class="webuploader-container" style="float: left; margin-right: 10px">
<div>
选择文件
<input type="file" name="file" class="webuploader-element-invisible" multiple="multiple">
</div>
</div>
<div id="UploadBtn" class="webuploader-pick" style="float: left; margin-right: 10px">开始上传</div>
<div id="StopBtn" class="webuploader-pick" style="float: left; margin-right: 10px">暂停上传</div>
</div>
</div>
</div>
</body>
</html>
BigFileUploadController.cs
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using System.Web;
using System.Web.Helpers;
using System.Web.Mvc;
using FileUpload.Models;
namespace FileUpload.Controllers
{
public class BigFileUploadController : FileBaseController
{
// GET: BigFileUpload
public ActionResult Index()
{
return View();
}
// GET: FileUpload
//解决文件上传最大4M的显示可在web.config中设置,当前设置,最大上传大小2GB,最大上传时间一小时
public ActionResult BigFileUp(string guid, string md5value, string chunks, string chunk, string id, string name,
string type, string lastModifiedDate, int size, HttpPostedFileBase file)
{
//全程没有做文件后缀或者类型验证,需要的应该在开始就做验证
//object lockObj = null;
if (Request.Files.Count == 0)
{
return Json(new {error = true});
}
string ex = Path.GetExtension(file.FileName);
string fileFullName = String.Empty;
string localPath = String.Empty;
try
{
localPath = Path.Combine(HttpRuntime.AppDomainAppPath, "Upload");
}
catch (Exception)
{
localPath = "D:\\代码\\ASP.NET\\FileUpload\\FileUpload\\Upload"; //单元测试用
}
//取得分块和信号信息
int fenkuai = 0;
int xuhao = 0;
if (chunks != null && chunk != null)
{
fenkuai = Convert.ToInt32(chunks);
xuhao = Convert.ToInt32(chunk);
//isOk = fenkuai;//每次写入文件后-1,到0了就可以合并了(已放弃)
}
else
{
//文件没有分块直接保存
fileFullName = Guid.NewGuid().ToString("N") + ex;
//file.SaveAs(Path.Combine(HttpRuntime.AppDomainAppPath + "\\Upload", fileFullName));
if (!SaveFile(localPath, fileFullName, file))
{
return Json(new {error = true});
}
else
{
}
#region 保存文件md5到数据库
FileModel model = new FileModel();
FileUpload.Models.FileInfo upfile = new FileUpload.Models.FileInfo();
upfile.FileMD5 = md5value;
upfile.FileName = fileFullName;
model.FileInfoSet.Add(upfile);
model.SaveChanges();
#endregion
return Json(new
{
jsonrpc = "2.0",
id = id,
filePath = "/Upload/" + fileFullName
});
}
string tempPath = "Upload";
if (guid != null)
{
tempPath = tempPath + "\\" + guid.ToString();
}
//string localPath = Path.Combine(HttpRuntime.AppDomainAppPath, tempPath);//保存的路径
tempPath = Path.Combine(HttpRuntime.AppDomainAppPath, tempPath); //保存的路径
//没有做文件类型验证
//fileFullName = Guid.NewGuid().ToString("N") + ex;
fileFullName = "temp" + xuhao.ToString() + ex;
//应该先把分块的文件存到以guid命名的临时文件夹下,待文件夹下的文件数目达到分块数目后拼接成一个文件,并删除临时文件
if (!SaveFile(tempPath, fileFullName, file))
{
return Json(new {error = true});
}
else
{
//分块文件保存成功后要判断是否合并文件
}
#region MyRegion
//if (!System.IO.Directory.Exists(tempPath))
//{
// System.IO.Directory.CreateDirectory(tempPath);//不存在该文件夹就新建一个
//}
//try
//{
// //if (isOk == 1)
// //{
// //}
// file.SaveAs(Path.Combine(tempPath, fileFullName));
// //isOk = isOk - 1;
//}
//catch (Exception)
//{
// //异常处理 Log4Net
// //return HttpNotFound();
// return Json(new { error = true });//新的错误返回方式,更加轻量!
//}
#endregion
//finally
if (xuhao == 0) //第一个分块负责上传的进程留下来合并文件
{
//此处有多线程问题,所以可能出现合并出多个文件的情况,而且下面只判断了文件数目,可能文件还没写入完成!(已解决,看上面)
//待文件夹下的文件数目达到分块数目后拼接成一个文件,并删除临时文件
//fileFullName文件夹
int count = 0;
DirectoryInfo TempFolder = new DirectoryInfo(tempPath);
foreach (var tempFile in TempFolder.GetFiles())
{
count = count + 1;
}
if (count == fenkuai)
{
//while (isOk != 0)
//{
// Thread.Sleep(1000);
//}
//lock (lockObject)
//{
//}
//达到合并的要求了
//序号从0开始
string path = Path.Combine(HttpRuntime.AppDomainAppPath, "Upload"); //保存的路径
//string path = Path.Combine(HttpRuntime.AppDomainAppPath, "Upload\\"+guid);//测试:保存的路径
string filefullname = Guid.NewGuid().ToString() + ex;
//下面应该用using块实现
FileStream fa = new FileStream(path + "\\" + filefullname, FileMode.Append, FileAccess.Write);
for (int i = 0; i < count; i++)
{
byte[] buffer = new byte[11 * 1024 * 1024];
//FileStream fileTemp = new FileStream(tempPath + "\\temp"+i+ex, FileMode.Open, FileAccess.Read,FileShare.ReadWrite);
//解决了文件占用问题
int tryTimes = 0;
FileStream fileTemp = null;
while (fileTemp == null)
{
try
{
fileTemp = new FileStream(tempPath + "\\temp" + i + ex, FileMode.Open, FileAccess.Read);
tryTimes++;
if (tryTimes > 100) //次数大于100就结束等待
{
return Json(new {error = true});
}
}
catch (Exception)
{
}
}
int buffersize = Convert.ToInt32(fileTemp.Length);
fileTemp.Read(buffer, 0, buffersize);
fa.Write(buffer, 0, buffersize);
//fileTemp.Read(buffer, 0, 10*1024*1024);
//fa.Write(buffer, 0, 10 * 1024 * 1024);
fileTemp.Flush();
//fileTemp.Close();
fileTemp.Dispose();
if (i == count - 1)
{
TempFolder.Delete(true); //删除temp目录
}
}
#region 将文件信息写入数据库
FileModel model = new FileModel();
FileUpload.Models.FileInfo upfile = new FileUpload.Models.FileInfo();
upfile.FileMD5 = md5value;
upfile.FileName = filefullname;
model.FileInfoSet.Add(upfile);
model.SaveChanges();
#endregion
fa.Flush();
//fa.Close();//关闭流
fa.Dispose();
}
}
return Json(new
{
jsonrpc = "2.0",
id = id,
filePath = "/Upload/" + fileFullName
});
}
public ActionResult IsMD5Exist(string fileMd5, string fileName, string fileID)
{
FileModel model = new FileModel();
FileUpload.Models.FileInfo file = new FileUpload.Models.FileInfo();
file = (from c in model.FileInfoSet
where c.FileMD5 == fileMd5
select c).FirstOrDefault();
//if (file == null)
//{
// return HttpNotFound();//代表服务器上没有这个文件
//}
//return Json(new//存在MD5相同的文件
//{
// Eixst = true
//});
if (file == null)
{
return Json("this file is not exist");
}
return Json("this file is exist");
}
}
}
ImagUpload文件夹下Index.cshtml
@{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<title>图片上传</title>
<!--支持IE9+ chrome fireFox-->
<script src="~/Scripts/jquery-2.1.4.min.js"></script>
<link href="~/Content/webuploader.css" rel="stylesheet"/>
<script src="~/Scripts/webuploader.nolog.js"></script>
<link href="~/Content/bootstrap.min.css" rel="stylesheet"/>
<script src="~/Scripts/bootstrap.min.js"></script>
<script type="text/javascript">
$(function() {
$list = $('#fileList');
var thumbnailHeight = 150;
var thumbnailWidth = 150;
//WebUploader实例
var uploader = WebUploader.create({
//设置选完文件后是否自动上传
auto: false,
//swf文件路径
//swf: BASE_URL + '~/FileUpload/Uploader.swf',
swf: '../FileUpload/Uploader.swf',
// 文件接收服务端。
server: '/ImagUpload/ImagUp',
// 选择文件的按钮。可选。
// 内部根据当前运行是创建,可能是input元素,也可能是flash.
pick: '#picker',
// 不压缩image, 默认如果是jpeg,文件上传前会压缩一把再上传!
//resize: false
//选择图片文件
accept: {
title: 'Images',
extensions: 'gif,jpg,jpeg,bmp,png',
mimeTypes: 'image/*'
}
});
// 当有文件被添加进队列的时候
uploader.on('fileQueued',
function(file) {
//$list.append('<div id="' + file.id + '" class="item">' +
// '<h4 class="info">' + file.name + '<button type="button" fileId="' + file.id + '" class="btn btn-danger btn-delete"><span class="glyphicon glyphicon-trash"></span></button></h4>' +
// '<p class="state">等待上传...</p>' +
// '</div>');
var $li = $('<div id="' +
file.id +
'" class="item">' +
'<h4 class="info">' +
file.name +
'<button type="button" fileId="' +
file.id +
'" class="btn btn-danger btn-delete"><span class="glyphicon glyphicon-trash"></span></button></h4>' +
'<p class="state">等待上传...</p>' +
'<img>' +
'</div>'),
$img = $li.find('img');
// $list为容器jQuery实例
$list.append($li);
//创建缩略图
uploader.makeThumb(file,
function(error, src) {
if (error) {
$img.replaceWith('<span>不能预览</span>');
return;
}
$img.attr('src', src);
},
thumbnailWidth,
thumbnailHeight);
//删除要上传的文件
//每次添加文件都给btn-delete绑定删除方法
$(".btn-delete").click(function() {
//console.log($(this).attr("fileId"));//拿到文件id
uploader.removeFile(uploader.getFile($(this).attr("fileId"), true));
$(this).parent().parent().fadeOut(); //视觉上消失了
$(this).parent().parent().remove(); //DOM上删除了
});
});
// 文件上传过程中创建进度条实时显示。
uploader.on('uploadProgress',
function(file, percentage) {
var $li = $('#' + file.id),
$percent = $li.find('.progress .progress-bar');
// 避免重复创建
if (!$percent.length) {
$percent = $('<div class="progress progress-striped active">' +
'<div class="progress-bar" role="progressbar" style="width: 0%">' +
'</div>' +
'</div>').appendTo($li).find('.progress-bar');
}
$li.find('p.state').text('上传中');
$percent.css('width', percentage * 100 + '%');
});
uploader.on('uploadSuccess',
function(file) {
$('#' + file.id).find('p.state').text('已上传');
$('#' + file.id).find(".progress").find(".progress-bar")
.attr("class", "progress-bar progress-bar-success");
$('#' + file.id).find(".info").find('.btn').fadeOut('slow'); //上传完后删除"删除"按钮
});
uploader.on('uploadError',
function(file) {
$('#' + file.id).find('p.state').text('上传出错');
//上传出错后进度条爆红
$('#' + file.id).find(".progress").find(".progress-bar")
.attr("class", "progress-bar progress-bar-danger");
//添加重试按钮
//为了防止重复添加重试按钮,做一个判断
//var retrybutton = $('#' + file.id).find(".btn-retry");
//$('#' + file.id)
if ($('#' + file.id).find(".btn-retry").length < 1) {
var btn = $('<button type="button" fileid="' +
file.id +
'" class="btn btn-success btn-retry"><span class="glyphicon glyphicon-refresh"></span></button>');
$('#' + file.id).find(".info").append(btn); //.find(".btn-danger")
}
$(".btn-retry").click(function() {
//console.log($(this).attr("fileId"));//拿到文件id
uploader.retry(uploader.getFile($(this).attr("fileId")));
});
});
uploader.on('uploadComplete',
function(file) { //上传完成后回调
//$('#' + file.id).find('.progress').fadeOut();//上传完删除进度条
//$('#' + file.id + 'btn').fadeOut('slow')//上传完后删除"删除"按钮
});
uploader.on('uploadFinished',
function() {
//上传完后的回调方法
//alert("所有文件上传完毕");
//提交表单
});
$("#UploadBtn").click(function() {
uploader.upload(); //上传
});
uploader.on('uploadAccept',
function(file, response) {
//if (uploader.errorCode) {
// // 通过return false来告诉组件,此文件上传有错。
// return false;
//}
if (response._raw == '{"error":true}') {
return false;
}
});
//重传指定文件
//function retry(file) {
// uploader.retry(file);
//}
});
</script>
</head>
<body>
<div class="container" style="margin-top: 50px">
<div id="uploader" class="container">
<div class="container">
<div id="fileList" class="uploader-list"></div> <!--存放文件的容器-->
</div>
<div class="btns container">
<div id="picker" class="webuploader-container" style="float: left; margin-right: 10px">
<div>
选择图片
<input type="file" name="file" class="webuploader-element-invisible" multiple="multiple">
</div>
</div>
<div id="UploadBtn" class="webuploader-pick" style="float: left">开始上传</div>
</div>
</div>
</div>
</body>
</html>
ImagUploadController.cs
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace FileUpload.Controllers
{
public class ImagUploadController : FileBaseController
{
public ViewResult Index()
{
return View();
}
// GET: ImagUpload
//解决文件上传最大4M的显示可在web.config中设置,当前设置,最大上传大小2GB,最大上传时间一小时
public ActionResult ImagUp(string id, string name, string type, string lastModifiedDate, int size,
HttpPostedFileBase file)
{
#region 判断文件后缀名
string ex = Path.GetExtension(file.FileName).ToLower(); //要统一转成大写或者小写
if (!IsFileExAcceptable(ex))
{
return Json(new {error = true});
}
#endregion
#region 或者: 验证文件类型file.ContentType,其实也是验证文件后缀
//if (file.ContentType != "image/gif" && file.ContentType != "image/jpg" && file.ContentType != "image/jpeg" && file.ContentType != "image/bmp" && file.ContentType != "image/png")
//{
// //文件类型不符合要求
// return Json(new { jsonrpc = 2.0, error = new { code = 102, message = "保存失败" }, id = "id" });
//}
#endregion
#region 真正验证文件类型!改后缀也不行
//FileStream fs = (FileStream)file.InputStream;
Stream fs = file.InputStream;
BinaryReader br = new BinaryReader(fs);
if (!IsRealImag(fs, br))
{
return Json(new {error = true});
}
#endregion
//开始保存文件
string fileFullName = String.Empty;
string localPath = Path.Combine(HttpRuntime.AppDomainAppPath, "Upload");
if (Request.Files.Count == 0)
{
//return HttpNotFound();
//return Json(new { jsonrpc = 2.0, error = new { code = 102, message = "保存失败" }, id = id });
return Json(new {error = true}); //新的错误返回方式,更加轻量!
}
fileFullName = Guid.NewGuid().ToString("N") + ex;
if (!SaveFile(localPath, fileFullName, file))
{
return Json(new {error = true});
}
else
{
return Json(new
{
jsonrpc = "2.0",
id = id,
filePath = "/Upload/" + fileFullName
});
}
#region 方法移到了FileBaseController
//if (!System.IO.Directory.Exists(localPath))
//{
// System.IO.Directory.CreateDirectory(localPath);
//}
//try
//{
// file.SaveAs(Path.Combine(localPath, fileFullName));
//}
//catch (Exception)
//{
// //异常处理 Log4Net
// //return HttpNotFound();
// return Json(new { error = true });//新的错误返回方式,更加轻量!
//}
//finally
//{
// br.Close();
// fs.Close();
//}
//return Json(new
//{
// jsonrpc = "2.0",
// id = id,
// filePath = "/Upload/" + fileFullName
//});
#endregion
}
/// <summary>
/// 判断文件后缀名是否可接受
/// </summary>
/// <param name="ex">.后缀名</param>
/// <returns></returns>
public bool IsFileExAcceptable(string ex)
{
//做文件类型验证 文件后缀名统一为小写
//gif,jpg,jpeg,bmp,png
if (ex != ".gif" && ex != ".jpg" && ex != ".jpeg" && ex != ".bmp" && ex != ".png")
{
//文件后缀不符合要求
return false;
}
else
{
return true;
}
}
/// <summary>
/// 真正的通过fileclass验证是否是真的图片,改后缀名也能验证出来
/// </summary>
/// <param name="fs">文件输入流</param>
/// <param name="br">二进制读入</param>
/// <returns></returns>
public bool IsRealImag(Stream fs, BinaryReader br)
{
//Stream fs = file.InputStream;
string fileClass = string.Empty;
//BinaryReader br = new BinaryReader(fs);
byte buffer;
byte[] b = new byte[2];
buffer = br.ReadByte();
b[0] = buffer;
fileClass = buffer.ToString();
buffer = br.ReadByte();
b[1] = buffer;
fileClass += buffer.ToString();
//br.Close(); 释放资源在finally语句块中,提前释放会将file的内容清空
//fs.Close();
if (fileClass != "7173" && fileClass != "255216" && fileClass != "6677" && fileClass != "13780"
) //jpe和jpeg fileclass相同
{
return false;
}
else
{
return true;
}
}
}
}
Web.config
<?xml version="1.0"?>
<!--
有关如何配置 ASP.NET 应用程序的详细信息,请访问
http://go.microsoft.com/fwlink/?LinkId=301880
-->
<configuration>
<configSections>
<!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
<section name="entityFramework"
type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
requirePermission="false" />
</configSections>
<appSettings>
<add key="webpages:Version" value="3.0.0.0" />
<add key="webpages:Enabled" value="false" />
<add key="ClientValidationEnabled" value="true" />
<add key="UnobtrusiveJavaScriptEnabled" value="true" />
</appSettings>
<!--
有关 web.config 更改的说明,请参见 http://go.microsoft.com/fwlink/?LinkId=235367。
可在 <httpRuntime> 标记上设置以下特性。
<system.Web>
<httpRuntime targetFramework="4.5" />
</system.Web>
-->
<system.web>
<compilation debug="true" targetFramework="4.5" />
<httpRuntime maxRequestLength="1048576" executionTimeout="3600" />
<!--设置最大上传大小和时间-->
<pages controlRenderingCompatibilityVersion="4.0" />
</system.web>
<system.webServer>
<!--configuration/system.webServer/security/requestFiltering/requestLimits@maxAllowedContentLength-->
<modules>
<remove name="FormsAuthentication" />
</modules>
<security>
<requestFiltering>
<requestLimits maxAllowedContentLength="2147483647">
<!--最大上传2GB-->
</requestLimits>
</requestFiltering>
</security>
</system.webServer>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Web.Helpers" publicKeyToken="31bf3856ad364e35" />
<bindingRedirect oldVersion="1.0.0.0-3.0.0.0" newVersion="3.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.WebPages" publicKeyToken="31bf3856ad364e35" />
<bindingRedirect oldVersion="1.0.0.0-3.0.0.0" newVersion="3.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" />
<bindingRedirect oldVersion="1.0.0.0-5.2.3.0" newVersion="5.2.3.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
<system.codedom>
<compilers>
<compiler language="c#;cs;csharp" extension=".cs"
type="Microsoft.CodeDom.Providers.DotNetCompilerPlatform.CSharpCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
warningLevel="4" compilerOptions="/langversion:6 /nowarn:1659;1699;1701" />
<compiler language="vb;vbs;visualbasic;vbscript" extension=".vb"
type="Microsoft.CodeDom.Providers.DotNetCompilerPlatform.VBCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
warningLevel="4"
compilerOptions="/langversion:14 /nowarn:41008 /define:_MYTYPE=\"Web\" /optionInfer+" />
</compilers>
</system.codedom>
<entityFramework>
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
<parameters>
<parameter value="mssqllocaldb" />
</parameters>
</defaultConnectionFactory>
<providers>
<provider invariantName="System.Data.SqlClient"
type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
</providers>
</entityFramework>
<connectionStrings>
<add name="FileModel"
connectionString="data source=.;initial catalog=FileUpload;integrated security=True;user id=sa;password=wu199010;MultipleActiveResultSets=True;App=EntityFramework"
providerName="System.Data.SqlClient" />
</connectionStrings>
</configuration>
截图