HTML5-WebSocket实现多文件同时上传
在传统的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事件对上传文件进度信息进行一个设置更新
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
|
/// <summary> </summary> /// Copyright © henryfan 2012
///Email: henryfan@msn.com
///HomePage: <a href="http://www.ikende.com%20%20%20%20%20%20%20/">http://www.ikende.com </a>
///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浏览器

핫 AI 도구

Undresser.AI Undress
사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover
사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool
무료로 이미지를 벗다

Clothoff.io
AI 옷 제거제

AI Hentai Generator
AI Hentai를 무료로 생성하십시오.

인기 기사

뜨거운 도구

메모장++7.3.1
사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전
중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기
강력한 PHP 통합 개발 환경

드림위버 CS6
시각적 웹 개발 도구

SublimeText3 Mac 버전
신 수준의 코드 편집 소프트웨어(SublimeText3)

뜨거운 주제











이 기사는 & lt; audio & gt를 사용하여 HTML5에 오디오를 포함시키는 방법을 설명합니다. 형식 선택에 대한 모범 사례 (MP3, OGG Vorbis), 파일 최적화 및 재생에 대한 JavaScript 컨트롤을 포함한 요소. 다중 오디오를 사용하는 것을 강조합니다

이 기사는 지리적 위치 API를 사용하여 사용자 위치 개인 정보 및 권한 관리, 권한 요청, 데이터 보안 보장 및 개인 정보 보호법 준수에 대한 모범 사례를 강조하는 것에 대해 설명합니다.

이 기사에서는 Viewport Meta 태그를 사용하여 모바일 장치의 페이지 스케일링을 제어하여 폭과 최적의 응답 성 및 성능을위한 초기 스케일과 같은 설정에 중점을 둡니다. character count : 159

이 기사에서는 HTML5 페이지 가시성 API를 사용하여 페이지 가시성을 감지하고 사용자 경험을 향상 시키며 리소스 사용량을 최적화하는 것에 대해 설명합니다. 주요 측면에는 미디어 일시 정지, CPU 부하 감소 및 가시성 변경에 기반한 분석 관리가 포함됩니다.

이 기사에서는 HTML5 양식을 작성하고 검증하는 방법을 설명합니다. 그것은 & lt; form & gt; 요소, 입력 유형 (텍스트, 이메일, 번호 등) 및 속성 (필수, 패턴, 최소, 최대). HTML5의 장점은 오래된 방법에 비해 형성됩니다

이 기사는 JavaScript를 사용하여 대화식 HTML5 게임을 만드는 자세한 내용입니다. 게임 디자인, HTML 구조, CSS 스타일, JavaScript 로직 (이벤트 처리 및 애니메이션 포함) 및 오디오 통합을 다룹니다. 필수 JavaScript 라이브러리 (Phaser, PI

이 기사는 HTML5 드래그 앤 드롭 API를 사용하여 대화식 사용자 인터페이스를 생성하고 요소를 드래그 가능하게 만들고 주요 이벤트를 처리하며 사용자 정의 피드백으로 사용자 경험을 향상시키는 방법을 자세히 설명합니다. 또한 일반적인 함정에 대해 설명합니다

이 기사에서는 실시간, 양방향 클라이언트 서버 커뮤니케이션을위한 HTML5 WebSockets API를 설명합니다. 클라이언트 측 (JavaScript) 및 서버 측 (Python/Flask) 구현에 대해 자세히 설명하여 확장 성, 상태 관리,
