HTML5 文件域+FileReader 分段读取文件并上传(八)-WebSocket
一、同时上传多个文件处理
HTML:
<div class="container">
<div class="panel panel-default">
<div class="panel-heading">分段读取文件:</div>
<div class="panel-body" id="bodyOne">
<input type="file" id="file" multiple/><br />
</div>
</div>
</div>
JS:
1.封装单文上传实例
//封装 单个文件上传实例
(function () {
var url = 'ws://localhost:55373/ashx/upload4.ashx';
//指定上传文件,创建上传操作对象
function uploadOperate(file) {
var _this = this;
this.reader = new FileReader();//读取文件对象
this.step = 1024 * 256;//每次读取文件字节数
this.curLoaded = 0; //当前读取位置
this.file = file; //当前文件对象
this.enableRead = true; //指定是否可读取,
this.total = file.size; //当前文件总大小
this.startTime = new Date(); //开始读取时间
//创建显示
this.createItem();
this.initWebSocket(function () {
_this.bindReader();
});
console.info('文件大小:' + this.total);
}
uploadOperate.prototype = {
//绑定读取事件
bindReader: function () {
var _this = this;
var reader = this.reader;
var ws = this.ws;
reader.onload = function (e) {
//判断是否能再次读取
if (_this.enableRead == false) return;
//根据当前缓冲区 控制读取速度
if (ws.bufferedAmount >= _this.step * 20) {
setTimeout(function () {
_this.loadSuccess(e.loaded);
}, 5);
console.info('---->进入等待');
} else {
_this.loadSuccess(e.loaded);
}
}
//开始读取
_this.readBlob();
},
//读取成功,操作处理
loadSuccess: function (loaded) {
var _this = this;
var ws = _this.ws;
//使用WebSocket 将二进制输出上传到服务器
var blob = _this.reader.result;
if (_this.curLoaded <= 0)
ws.send(_this.file.name);
ws.send(blob);
//当前发送完成,继续读取
_this.curLoaded += loaded;
if (_this.curLoaded < _this.total) {
_this.readBlob();
} else {
//发送读取完成
ws.send('发送完成');
//读取完成
console.log('总共上传:' + _this.curLoaded + ',总共用时:' + (new Date().getTime() - _this.startTime.getTime()) / 1000);
}
//显示进度等
_this.showProgress();
},
//创建显示项
createItem: function () {
var _this = this;
var blockquote = document.createElement('blockquote');
var abort = document.createElement('input');
abort.type = 'button';
abort.value = '中止';
abort.onclick = function () {
_this.stop();
};
blockquote.appendChild(abort);
var containue = document.createElement('input');
containue.type = 'button';
containue.value = '继续';
containue.onclick = function () {
_this.containue();
};
blockquote.appendChild(containue);
var progress = document.createElement('progress');
progress.style.width = '400px';
progress.max = 100;
progress.value = 0;
blockquote.appendChild(progress);
_this.progressBox = progress;
var status = document.createElement('p');
status.id = 'Status';
blockquote.appendChild(status);
_this.statusBox = status;
document.getElementById('bodyOne').appendChild(blockquote);
},
//显示进度
showProgress: function () {
var _this = this;
var percent = (_this.curLoaded / _this.total) * 100;
_this.progressBox.value = percent;
_this.statusBox.innerHTML = percent;
},
//执行读取文件
readBlob: function () {
var blob = this.file.slice(this.curLoaded, this.curLoaded + this.step);
this.reader.readAsArrayBuffer(blob);
},
//中止读取
stop: function () {
this.enableRead = false;
this.reader.abort();
console.log('读取中止,curLoaded:' + this.curLoaded);
},
//继续读取
containue: function () {
this.enableRead = true;
this.readBlob();
console.log('读取继续,curLoaded:' + this.curLoaded);
},
//初始化 绑定创建连接
initWebSocket: function (onSuccess) {
var _this = this;
var ws = this.ws = new WebSocket(url); //初始化上传对象
ws.onopen = function () {
console.log('connect创建成功');
if (onSuccess)
onSuccess();
}
ws.onmessage = function (e) {
var data = e.data;
if (isNaN(data) == false) {
console.info('后台接收成功:' + data);
} else {
console.info(data);
}
}
ws.onclose = function (e) {
//中止读取
_this.stop();
console.log('connect已经断开');
}
ws.onerror = function (e) {
//中止读取
_this.stop();
console.log('发生异常:' + e.message);
}
}
};
window.uploadOperate = uploadOperate;
})();
2.绑定页面处理
/*
* 测试WebSocket多文件上传
* 上传速度取决于 每次send() 的数据大小 ,Google之所以相对比较慢,是因为每次send的数据量太小
*/
var fileBox = document.getElementById('file');
fileBox.onchange = function () {
var files = this.files;
for (var i = 0; i < files.length; i++) {
var file = files[i];
var operate = new uploadOperate(file);
}
}
服务器后台封装处理:
public void ProcessRequest(HttpContext context)
{
//处理WebSocket 请求
context.AcceptWebSocketRequest(DoWork);
}
/// <summary>
/// 委托处理函数定义
/// </summary>
/// <param name="context">当前WebSocket上下文</param>
/// <returns></returns>
public async Task DoWork(AspNetWebSocketContext context)
{
//1.获取当前WebSocket 对象
WebSocket socket = context.WebSocket;
string filename = "";
byte[] bufferAll = new byte[1024 * 256 * 2];//缓存接收文件
//Array.Copy
//byte[] bufferAll = new byte[];
int loaded = 0; //当前缓冲数量
//2.监视相应
while (true)
{
/*
* 此处缓存数组指定读取客户端数据的长度
* 如果客户端发送数据超过当前缓存区,则会读取多次
*/
ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[1024 * 256]);
//接收客户端信息
CancellationToken token;
WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, token);
if (socket.State == WebSocketState.Open)
{
//判断是否已经到了最后
int curLength = Math.Min(buffer.Array.Length, result.Count);
try
{
//判断用户传入的类型进行处理
if (result.MessageType == WebSocketMessageType.Text)
{
string msg = Encoding.UTF8.GetString(buffer.Array, 0, curLength);
if (msg == "发送完成")
{
//发送完成,全部写入文件
string str = SaveFile(filename, bufferAll, loaded);
loaded = 0;
ArraySegment<byte> echor = new ArraySegment<byte>(Encoding.UTF8.GetBytes(curLength.ToString()));
await socket.SendAsync(echor, WebSocketMessageType.Text, true, CancellationToken.None);
}
else
{
filename = msg;
msg = string.Format("服务器链接数量:{0},当前链接ID={1},接收文件名:{2}",
AspNetWebSocketContext.ConnectionCount, context.AnonymousID, filename);
ArraySegment<byte> echor = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msg));
await socket.SendAsync(echor, WebSocketMessageType.Text, true, CancellationToken.None);
}
}
else if (result.MessageType == WebSocketMessageType.Binary)
{
var temp = loaded + curLength;
if ((temp) > bufferAll.Length)
{
//先写入文件
string msg = SaveFile(filename, bufferAll, loaded);
//添加到缓冲区
Array.Copy(buffer.Array, 0, bufferAll, 0, curLength);
loaded = curLength;
//返回相应
ArraySegment<byte> echor = new ArraySegment<byte>(Encoding.UTF8.GetBytes(curLength.ToString()));
await socket.SendAsync(echor, WebSocketMessageType.Text, true, CancellationToken.None);
}
else
{
//添加到缓冲区
Array.Copy(buffer.Array, 0, bufferAll, loaded, curLength);
loaded = temp;
}
}
}
catch (Exception ex)
{
}
}
else { break; }
}
}
/// <summary>
/// 追加二进制数据到文件
/// </summary>
public string SaveFile(string file, byte[] buffer, int Length)
{
//去除文件名中的前后空格
file = file.Trim();
string fullname = @"F:\JavaScript_Solution\H5Solition\UploadWebForm\content\" + file;
try
{
FileStream fs = new FileStream(fullname, FileMode.Append, FileAccess.Write);
try
{
//byte[] result = buffer.ToArray();
//fs.Write(result, 0, Length);
fs.Write(buffer, 0, Length);
}
finally
{
fs.Close();
}
return "保存文件成功";
}
catch (Exception ex)
{
return ex.Message;
}
}
运行结果显示:
更多Demo源代码:
http://git.oschina.net/tiama3798/HTML5Demo/tree/WebSocket/
http://git.oschina.net/tiama3798/HTML5Demo/tree/FileReader/
还没有评论,来说两句吧...