环境:见上一章
原理:服务器端代码将webuploader分片文件,追加到文件上。
结论:1、asp.net做服务器端,单线程条件下(webuploader的threads值为1),测试上传1.7G文件没有问题;不支持多线程,可改进;2、同样代码移植到 j2ee springMVC 环境下,仅能支持到620M左右,主要原因为java环境下无法有效释放文件流。
目标:将现有流程优化,多进程、分片上传,在文档结尾处将文件合并,目前无时间安排此优化。
1、web.config配置可参见前章。
2、html代码如下:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title></title>
<meta charset="utf-8" />
<link href="dist/webuploader.css" rel="stylesheet" />
<script src="dist/jquery.js"></script>
<script src="dist/webuploader.js"></script>
</head>
<body>
<div class="wu-example">
<!--用来存放文件信息-->
<div id="thelist" class="uploader-list"></div>
<div class="btns">
<div id="picker">选择文件</div>
<button id="ctlBtn" class="btn btn-default">开始上传</button>
</div>
</div>
<script>
var uploader = WebUploader.create({
// swf文件路径
swf: '/dist/Uploader.swf',
// 文件接收服务端。
server: 'fileuploadchunk.ashx',
chunked: true,
threads: 1,
fromData : { guid : 'guid'} ,
// 选择文件的按钮。可选。
// 内部根据当前运行是创建,可能是input元素,也可能是flash.
pick: '#picker',
// 不压缩image, 默认如果是jpeg,文件上传前会压缩一把再上传!
resize: false
});
uploader.on('beforeFileQueued', function (file) {
debugger
});
// 当有文件被添加进队列的时候
uploader.on('fileQueued', function (file) {
//alert(123);
$("#thelist").append('<div id="' + file.id + '" class="item">' +
'<h4 class="info">' + file.name + '</h4>' +
'<p class="state">等待上传...</p>' +
'</div>');
});
uploader.on('uploadSuccess', function (file) {
$('#' + file.id).find('p.state').text('已上传');
});
uploader.on('uploadError', function (file) {
$('#' + file.id).find('p.state').text('上传出错');
});
uploader.on('uploadComplete', function (file) {
$('#' + file.id).find('.progress').fadeOut();
});
$("#ctlBtn").on('click', function () {
if ($(this).hasClass('disabled')) {
return false;
}
uploader.options.formData.guid = Math.random();
uploader.upload();
});
</script>
</body>
</html>
3、一般处理程序(fileuploadchunk.ashx),代码如下:
<%@ WebHandler Language="C#" Class="fileuploadchunk" %>
using System;
using System.Web;
using System.Linq;
using System.IO;
public class fileuploadchunk : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
context.Response.ContentType = "text/plain";
if (context.Request.Form.AllKeys.Any(m => m == "chunk"))
{
int chunk = Convert.ToInt32(context.Request.Form["chunk"]); // 当前分片
int chunks = Convert.ToInt32(context.Request.Form["chunks"]); // 分片总计
string folder = context.Server.MapPath("~/Upload/");
string filename = folder + context.Request.Form["guid"];
// FileStream addFile = new FileStream(filename, FileMode.Append, FileAccess.Write); // 前端 threads= 1 可用
FileStream addFile = new FileStream(filename, FileMode.Append, FileAccess.Write, FileShare.ReadWrite, 1024, true); // 前端 threads值> 1 可用
BinaryWriter AddWriter = new BinaryWriter(addFile);
HttpPostedFile file = context.Request.Files[0];
Stream stream = file.InputStream;
BinaryReader TempReader = new BinaryReader(stream);
AddWriter.Write(TempReader.ReadBytes((int)stream.Length));
TempReader.Close();
stream.Close();
AddWriter.Close();
addFile.Close();
TempReader.Dispose();
stream.Dispose();
AddWriter.Dispose();
addFile.Dispose();
//如果是最后一个分片,则重命名临时文件为上传的文件名
if (chunk == (chunks - 1))
{
FileInfo fileinfo = new FileInfo(filename);
fileinfo.MoveTo(context.Server.MapPath("~/Upload/" + context.Request.Files[0].FileName));
}
}
else // 没有分片直接保存
{
context.Request.Files[0].SaveAs(context.Server.MapPath("~/Upload/" + context.Request.Files[0].FileName));
}
context.Response.Write("success");
}
public bool IsReusable
{
get
{
return false;
}
}
}