HTML5-WebSocket实现多文件同时上传

夏辰吖_2573

夏辰吖_2573

2016-05-17

2552人浏览

原创

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

实现功能


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



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


FileInfo类封装


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


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
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
        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.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中接受系统文件拖放进来并不需要做复杂的事情,只需要针对容器元素绑定相关事件即可.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
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的教程可以得到帮助,详细看http://www.html5rocks.com/zh/tutorials/file/dndfiles/


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


1
2
3
4
5
6
7
8
9
10
function onFileOpen(files) {
            if (files.length > 0) {
                for (var i = 0; i
                    var info = new FileInfo(files[i], 32768);
                    uploads.push(info);
                    info.UploadProcess = onUploadProcess;
                    addUploadItem(info);
                }
            }
        }


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

360智脑
360智脑

一款AI工具,主要用于360旗下ChatGPT类产品,适合需要提升相关任务效率的用户。

下载

1
2
3
4
5
function onUploadProcess(file) {
            $('#p_' + file.ID).progressbar({ value: (file.PageIndex / file.Pages) * 100,
                text: file.FileName + '[' + file.UploadBytes + '/' + file.Size + ']'
            });
        }


C#服务端


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


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
///
    /// Copyright © henryfan 2012        
    ///Email:   henryfan@msn.com    
    ///HomePage:    http://www.ikende.com       
    ///CreateTime:  2012/12/14 21:13:34
    ///
    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 (642.65 kb) 


演示地址:http://html5.ikende.com/upload.htm 使用chrome或IE10浏览器

前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!

相关文章

HTML速学教程(入门课程)
HTML速学教程(入门课程)

HTML怎么学习?HTML怎么入门?HTML在哪学?HTML怎么学才快?不用担心,这里为大家提供了HTML速学教程(入门课程),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
Go-Zero API开发使用教程
Go-Zero API开发使用教程

本专题聚焦Go-Zero的API开发,拆解.api描述文件的语法结构、路由与分组定义、参数绑定与校验规则,说明统一响应体、JWT鉴权、跨域与接口文档生成的落地方式,并给出网关聚合与接口测试的实践建议。

2026.11.12

80

15

Go-Zero安装与goctl环境配置教程
Go-Zero安装与goctl环境配置教程

本专题围绕Go-Zero的安装与工具链配置展开,讲清Go版本要求、goctl安装方式、代理镜像、protoc依赖与环境变量设置,说明多版本共存、升级回退与CI流水线安装的做法,并整理安装阶段的常见报错与验证步骤。

2026.11.12

60

15

Go-Zero零基础入门教程
Go-Zero零基础入门教程

本专题整理Go-Zero的入门知识,从框架定位、环境准备到跑通第一个API服务,讲清目录分层、配置加载、日志与中间件的基本用法,并对比Gin、Kratos的差异,帮助Go开发者建立整体认知,判断它是否适合当前项目。

2026.11.12

40

15

Postman身份认证怎么配置
Postman身份认证怎么配置

本专题从实际API接口调试场景出发,讲解Postman身份认证的完整配置流程,包括常见认证协议介绍、授权参数设置、访问令牌填写、OAuth 2.0授权及认证失败排查,帮助用户正确完成接口授权与访问验证。

2026.11.06

140

12

Postman请求头Headers怎么设置
Postman请求头Headers怎么设置

围绕Postman HTTP请求头配置展开,讲解Headers选项的具体使用方式,包括Key和Value参数填写、请求头信息添加、常见Header字段设置及请求头修改方法,帮助用户解决接口调试过程中遇到的请求头配置问题。

2026.11.06

120

13

Postman接口请求发送教程
Postman接口请求发送教程

详细介绍Postman接口请求的创建与发送方法,涵盖GET和POST请求、URL配置、请求参数、Headers请求头、Body请求体设置以及响应结果查看,帮助用户掌握Postman接口请求的完整操作流程。

2026.11.06

120

10

DBeaver怎么导入数据
DBeaver怎么导入数据

DBeaver数据导入专题,整理Excel、CSV、SQL、TXT等常见文件的数据导入方法,涵盖目标数据库选择、数据表创建、字段映射、数据类型设置及导入参数配置等操作,帮助用户将本地文件中的数据写入数据库,并了解批量导入、重复数据处理和导入失败等常见问题的解决方法。

2026.11.05

100

12

DBeaver安全防护教程大全
DBeaver安全防护教程大全

DBeaver安全防护专题,围绕数据库连接安全、账号密码保护和访问权限管理展开,整理SSL/TLS加密连接、SSH隧道、数据库凭据保存及证书验证等配置方法,同时介绍敏感信息保护、远程连接风险和高权限账号使用等注意事项,帮助用户提高数据库日常管理的安全性。

2026.11.05

80

12

DBeaver连接创建与配置教程
DBeaver连接创建与配置教程

本专题聚焦DBeaver数据库连接配置与管理,覆盖从新建连接、选择数据库类型到填写连接参数和验证连接的完整流程。针对MySQL、PostgreSQL、SQL Server等常见数据库,整理相应的连接设置方法,并提供驱动缺失、认证失败和连接异常等问题的排查方向。

2026.11.04

100

16

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程