HTML5+WebSocket实现多文件同时上传的实例


Posted in HTML / CSS onDecember 29, 2016

在传统的HTTP应用上传文件想要同时上传多个文件并查看上传进度是一件很麻烦的事情,当然现在也有一些基于SWF的文件上传组件提供这种的便利性.到了HTML5下对文件的读取和上传的控制方面就非常灵活,HTML5提供一系列的AIP进行文件读取,包括计取文件某一块的内容也非常方便,结合Websocket进行文件的传输就变得更加方便和灵活.下面通过使用HTML5结合websocet简单地实现多文件同时上传应用.

实现功能

大概预览一下需要做的功能:

HTML5+WebSocket实现多文件同时上传的实例

主要功能是用户可以直接把文件夹的文件直接拖放到网页中,并进行上传,在上传的过程中显示上传进度信息.

FileInfo类封装

为了方便读取文件信息,在原有File的基础封装了一个简单文件信息读取的对象类.

function FileInfo(file, pagesize) {

    this.Size = file.size;

    this.File = file;

    this.FileType = file.type;

    this.FileName = file.name;

    this.PageSize = pagesize;

    this.PageIndex = 0;

    this.Pages = 0;

    this.UploadError = null;

    this.UploadProcess = null;

    this.DataBuffer = null;

    this.UploadBytes = 0;

    this.ID = Math.floor(Math.random() * 0x10000).toString(16);

    this.LoadCallBack = null;

    if (Math.floor(this.Size % this.PageSize) > 0) {

        this.Pages = Math.floor((this.Size / this.PageSize)) + 1;

 

    }

    else {

        this.Pages = Math.floor(this.Size / this.PageSize);

 

    }

 

}

FileInfo.prototype.Reset = function () {

    this.PageIndex = 0;

    this.UploadBytes = 0;

}

FileInfo.prototype.toBase64String = function () {

    var binary = ''

    var bytes = new Uint8Array(this.DataBuffer)

    var len = bytes.byteLength;

 

    for (var i = 0; i < len; i++) {

        binary += String.fromCharCode(bytes[i])

    }

    return window.btoa(binary);

}

FileInfo.prototype.OnLoadData = function (evt) {

    var obj = evt.target["tag"];

 

    if (evt.target.readyState == FileReader.DONE) {

        obj.DataBuffer = evt.target.result;

        if (obj.LoadCallBack != null)

            obj.LoadCallBack(obj);

 

    }

    else {

        if (obj.UploadError != null)

            obj.UploadError(fi, evt.target.error);

    }

 

}

 

FileInfo.prototype.Load = function (completed) {

    this.LoadCallBack = completed;

    if (this.filereader == null || this.filereader == undefined)

        this.filereader = new FileReader();

    var reader = this.filereader;

    reader["tag"] = this;

    reader.onloadend = this.OnLoadData;

    var count = this.Size - this.PageIndex * this.PageSize;

    if (count > this.PageSize)

        count = this.PageSize;

    this.UploadBytes += count;

    var blob = this.File.slice(this.PageIndex * this.PageSize, this.PageIndex * this.PageSize + count);

 

    reader.readAsArrayBuffer(blob);

};

 

FileInfo.prototype.OnUploadData = function (file) {

    var channel = file._channel;

    var url = file._url;

    channel.Send({ url: url, parameters: { FileID: file.ID, PageIndex: file.PageIndex, Pages: file.Pages, Base64Data: file.toBase64String()} }, function (result) {

        if (result.status == null || result.status == undefined) {

            file.PageIndex++;

            if (file.UploadProcess != null)

                file.UploadProcess(file);

            if (file.PageIndex < file.Pages) {

                file.Load(file.OnUploadData);

            }

        }

        else {

 

            if (file.UploadError != null)

                file.UploadError(file, data.status);

        }

    });

}

 

FileInfo.prototype.Upload = function (channel, url) {

    var fi = this;

    channel.Send({ url: url, parameters: { FileName: fi.FileName, Size: fi.Size, FileID: fi.ID} }, function (result) {

        if (result.status == null || result.status == undefined) {

            fi._channel = channel;

            fi._url = result.data;

            fi.Load(fi.OnUploadData);

        }

        else {

            if (file.UploadError != null)

                file.UploadError(fi, result.status);

        }

    });

 

}

类的处理很简单,通过file初始化并指定分块大小来实始化一些文件信息,如页数量页大小等.当然最重要还封装文件对应的Upload方法,用于把文件块信息打包成base64信息通过Websocket的方式发送到服务器.

文件拖放

在HTML5中接受系统文件拖放进来并不需要做复杂的事情,只需要针对容器元素绑定相关事件即可.

function onDragEnter(e) {

            e.stopPropagation();

            e.preventDefault();

        }

 

        function onDragOver(e) {

            e.stopPropagation();

            e.preventDefault();

            $(dropbox).addClass('rounded');

        }

 

        function onDragLeave(e) {

            e.stopPropagation();

            e.preventDefault();

            $(dropbox).removeClass('rounded');

        }

 

        function onDrop(e) {

            e.stopPropagation();

            e.preventDefault();

            $(dropbox).removeClass('rounded');

            var readFileSize = 0;

            var files = e.dataTransfer.files;

            if (files.length > 0) {

                onFileOpen(files);

            }

 

        }

只需要在onDrop过程中获取相关拖放文件即可,这些可能通过一些HTML5的教程可以得到帮助。

这时候只需要针对选择的文件构建相关FileInfo对象,并调用上传方法即可.

function onFileOpen(files) {

            if (files.length > 0) {

                for (var i = 0; i < files.length; i++) {

                    var info = new FileInfo(files[i], 32768);

                    uploads.push(info);

                    info.UploadProcess = onUploadProcess;

                    addUploadItem(info);

                }

            }

        }

通过UploadProcess事件对上传文件进度信息进行一个设置更新

function onUploadProcess(file) {

            $('#p_' + file.ID).progressbar({ value: (file.PageIndex / file.Pages) * 100,

                text: file.FileName + '[' + file.UploadBytes + '/' + file.Size + ']'

            });

        }

C#服务端

借助于Beetle对websocket的支持对应服务端的实现就非常简单了

/// <summary>

    /// Copyright © henryfan 2012        

    ///CreateTime:  2012/12/14 21:13:34

    /// </summary>

    public class Handler

    {

        public void UploadPackage(string FileID, int PageIndex, int Pages, string Base64Data)

        {

            Console.WriteLine("FileID:{2},PageIndex:{0} Pages:{1} DataLength:{3}", PageIndex, Pages, FileID,Base64Data.Length);

 

        }

        public string UploadFile(string FileID, string FileName, long Size)

        {

            Console.WriteLine("FileID:{2},FileName:{0} Size:{1}", FileName, Size, FileID);

            return "Handler.UploadPackage";

        }

    }

服务端方法有两个一个是上传文件请求,和一个上传文件块接收方法.

总结

只需要以上简单的代码就能实现多文件同时上传功能,在这采用json来处理上传的信息,所以文件流要进行一个base64的编码处理,由于websocket浏览提交的数据一般都有MASK处理再加上base64那损耗相对来说比较重,实际上websocket有提供流的数据包格式(arraybuffer);当然这种处理在操作上就没有json来得方便简单.

下载代码:WebSocketUpload.rar  

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

HTML / CSS 相关文章推荐
CSS3动画之利用requestAnimationFrame触发重新播放功能
Sep 11 HTML / CSS
纯css3实现鼠标经过图片显示描述的动画效果
Sep 01 HTML / CSS
css3的transform造成z-index无效解决方案
Dec 04 HTML / CSS
通过CSS3的object-fit来调整图片适配尺寸的技巧简介
Feb 27 HTML / CSS
浅谈CSS3特性查询(Feature Query: @supports)功能简介
Jul 31 HTML / CSS
详解CSS3选择器:nth-child和:nth-of-type之间的差异
Sep 18 HTML / CSS
HTML5的video标签的浏览器兼容性增强方案分享
May 19 HTML / CSS
利用html5 file api读取本地文件示例(如图片、PDF等)
Mar 07 HTML / CSS
详解html2canvas截图不能截取圆角图片的解决方案
Jan 30 HTML / CSS
HTML5新标签兼容——&gt; 的两种方法
Sep 12 HTML / CSS
CSS几步实现赛博朋克2077风格视觉效果
Jun 16 HTML / CSS
CSS三大特性继承性、层叠性和优先级详解
Jan 18 HTML / CSS
详解前端HTML5几种存储方式的总结
Dec 27 #HTML / CSS
HTML5利用约束验证API来检查表单的输入数据的代码实例
Dec 20 #HTML / CSS
基于zepto的插件之移动端无缝向上滚动并上下触摸滑动实例代码
Dec 20 #HTML / CSS
html5 postMessage解决跨域、跨窗口消息传递方案
Dec 20 #HTML / CSS
详解HTML5中表单验证的8种方法介绍
Dec 19 #HTML / CSS
【HTML5】3D模型--百行代码实现旋转立体魔方实例
Dec 16 #HTML / CSS
使用spring mvc+localResizeIMG实现HTML5端图片压缩上传的功能
Dec 16 #HTML / CSS
You might like
地球防卫队:陪着奥特曼打小怪兽的人类力量 那些经典队服
2020/03/08 日漫
mysql 全文搜索 技巧
2007/04/27 PHP
PHP5 操作MySQL数据库基础代码
2009/09/29 PHP
解析PHP中$_FILES的使用以及注意事项
2013/07/05 PHP
抛弃 PHP 代价太高
2016/04/26 PHP
Mac系统下安装PHP Xdebug
2018/03/30 PHP
extjs 列表框(multiselect)的动态添加列表项的方法
2009/07/31 Javascript
jquery 多行文本框(textarea)高度变化
2013/07/03 Javascript
Js与下拉列表处理问题解决
2014/02/13 Javascript
BootStrap中Tab页签切换实例代码
2016/05/30 Javascript
利用jsonp跨域调用百度js实现搜索框智能提示
2016/08/24 Javascript
BootStrap Fileinput初始化时的一些参数
2016/12/30 Javascript
浅谈angular2的http请求返回结果的subcribe注意事项
2017/03/01 Javascript
为Jquery EasyUI 组件加上清除功能的方法(详解)
2017/04/13 jQuery
js和jquery中获取非行间样式
2017/05/05 jQuery
关于单文件组件.vue的使用
2018/09/20 Javascript
vue实现文字横向无缝走马灯组件效果的实例代码
2019/04/09 Javascript
JS FormData对象使用方法实例详解
2020/02/12 Javascript
基于node+websocket+html实现腾讯课堂聊天室聊天功能
2020/03/04 Javascript
15分钟上手vue3.0(小结)
2020/05/20 Javascript
[27:53]2014 DOTA2华西杯精英邀请赛 5 24 NewBee VS iG
2014/05/26 DOTA
python爬虫入门教程之糗百图片爬虫代码分享
2014/09/02 Python
讲解Python中if语句的嵌套用法
2015/05/14 Python
spark dataframe 将一列展开,把该列所有值都变成新列的方法
2019/01/29 Python
Python内建序列通用操作6种实现方法
2020/03/26 Python
浅谈python 调用open()打开文件时路径出错的原因
2020/06/05 Python
世界顶级户外运动品牌折扣网站:LeftLane Sports
2019/06/12 全球购物
JAVA中的关键字有什么特点
2014/03/07 面试题
体育专业学生自我评价范文
2014/01/17 职场文书
探亲假请假条
2014/04/11 职场文书
民主评议教师党员自我评价
2015/03/04 职场文书
庆元旦主持词
2015/07/06 职场文书
大学生创业计划书常用模板
2019/08/07 职场文书
二年级作文之动物作文
2019/11/13 职场文书
阿里云服务器搭建Php+Apache运行环境的详细过程
2021/05/15 PHP
CSS文本阴影 text-shadow 悬停效果详解
2022/05/25 HTML / CSS