如何实现HTML5文件断点续传

html-css026

如何实现HTML5文件断点续传,第1张

实现HTML5文件断点续传

一、实现文件多选

HTML5的<input>新增了"multiple"属性,该属性可接受多个值的文件上传字段

<input type="file" multiple="multiple" name="file" id="file">

添加了该属性用户就可以在弹出的对话框中一次性选择多个文件了

二、实现文件从计算机拖拽到网页以及添加文件队列功能

这里我们用 dragover 和 drop 两个事件来管理文件拖拽的功能

其中 dragover 用来处理在指定的元素上移动时的事件,这里我们通过给body绑定dragover时间来处理页面中拖动文件的事件

document.body.addEventListener('dragover', dragFile, false)

function dragFile(evt) {

evt.stopPropagation()

evt.preventDefault()

evt.dataTransfer.dropEffect = 'copy'

}

用 drop 事件来处理鼠标松开时候的事件,此时应该将用户拖动过来的文件加入到上传队列中,以供后续的处理

document.body.addEventListener('drop', dropFile, false)

function dragFile(evt) {

evt.stopPropagation()

evt.preventDefault()

// dataTransfer.files属性可以获取到所有拖动选择的文件,通过遍历可以读取到所有文件的信息。

// 遍历每个文件可以获取到文件的 name、size、type、lastModifiedDate等关键信息

var files = evt.dataTransfer.files

// addfile 方法 用来添加上传文件队列,在input的change事件中也需要调用

// 该方法首先检查有无文件正在上传中,如果有就将后续加入的文件放到上传队列中,如果没有文件正在上传就直接执行上传命令

addfile(files)

}

三、文件续传原理

目前比较常用的断点续传的方法有两种,一种是通过websocket接口进行文件上传,另一种是通过ajax,两种方法各有千秋,虽然websocket听起来比较高端些~ 但是除了用了不同的协议外其他的算法基本上都是很相似的,并且服务端要开启ws接口,这里用相对方便的ajax来说明断点上传的思路。

说来说去,断点续传最核心的内容就是把文件“切片”然后再一片一片的传给服务器,但是这看似简单的上传过程却有着无数的坑。

首先是文件的识别,一个文件被分成了若干份之后如何告诉服务器你切了多少块,以及最终服务器应该如何把你上传上去的文件进行合并,这都是要考虑的。

因此在文件开始上传之前,我们和服务器要有一个“握手”的过程,告诉服务器文件信息,然后和服务器约定切片的大小,当和服务器达成共识之后就可以开始后续的文件传输了。

前台要把每一块的文件传给后台,成功之后前端和后端都要标识一下,以便后续的断点。

当文件传输中断之后用户再次选择文件就可以通过标识来判断文件是否已经上传了一部分,如果是的话,那么我们可以接着上次的进度继续传文件,以达到续传的功能。

四、文件的前端切片

有了HTML5 的 File api之后切割文件比想想的要简单的多的多。

只要用slice 方法就可以了

var packet = file.slice(start, end)

参数start是开始切片的位置,end是切片结束的位置 单位都是字节。通过控制start和end 就可以是实现文件的分块

file.slice(0,1000)

file.slice(1000,2000)

file.slice(2000,3000)

// ......

五、文件片段的上传

上一部我们通过slice方法把文件分成了若干块,接下来要做的事情就是把这些碎片传到服务器上。

这里我们用ajax的post请求来实现

textpop-up

var xhr = new XMLHttpRequest()

var url = xxx // 文件上传的地址 可以包括文件的参数 如文件名称 分块数等以便后台处理

xhr.open('POST', url, true)

xhr.onload = function (e){

// 判断文件是否上传成功,如果成功继续上传下一块,如果失败重试该快

}

xhr.upload.onprogress = function(e){

// 选用 如果文件分块大小较大 可以通过该方法判断单片文件具体的上传进度

// e.loaded 该片文件上传了多少

// e.totalSize 该片文件的总共大小

}

xhr.send(packet)

1、文件过大会导致带宽资源紧张,请求速度下降 ;

2、如果上传过程中服务中断、网络中断 、页面崩溃,可能会导致文件重新开始上传。

前端选择文件后上传,后端在处理文件过程中,首先会将文件加载到 运行内存中 ,之后再调用相应的API进行 写入硬盘 内存的操作,完成整个文件的上传。

但这样直接上传文件,可能会因为某个环节出了问题导致整个流程的雪崩,所以大文件直接上传是不可取的。

解决问题最好办法是 分片断点续传 ,该方式主要是针对 大文件(比如100M以上的文件)

顾名思义就是 断点 续传

在文件上传过程中,将一个要上传的文件 分成N块 ,然后使用 多线程并发多块上传 ,因为某种原因导致上传被中断或暂停,此时中断或暂停的位置就成为 断点

前端每上传一片,将会被加载到 运行内存中 ,加载完毕后再写入硬盘,此时运行内存的临时变量会被释放,然后此临时变量会被下一片占用,再进行写入,释放...

意思是指从中断的位置继续上传剩下的部分文件,而不是从头开始上传。

上传完毕后,在服务端进行合并(合并的操作是在后端进行的,前端只是调用接口,合并的方式是由后端决定的,到底是上传一片就合并一片,或者是上传所有的之后整体进行合并)。

方式:

html5z之前的方式是 flash activeX

html5提供了文件二进制流进行分割的slice方法。

文件的分片,一般在2-5M之间。这一步得到了每一片文件的内容、每一块的序号、每一块的大小、总块数等数据。

这里提供了两个方法;一种是用SparkMD5.hashBinary( ) 直接将整个文件的二进制码传入直接返回文件的md5、这种方法对于小文件会比较有优势——简单并且速度快。

另一种方法是利用js中File对象的slice( )方法(File.prototype.slice( ))将文件分片后逐个传入spark.appendBinary( )方法来计算、最后通过spark.end( )方法输出结果,很明显,这种方法对于大型文件会非常有利——不容易出错,并且能够提供计算的进度信息

第一种方式:

第二种方式

用C实现断点续传的功能,详细点的实现原理是什么嘞

于HTTP 协议的多执行绪下载和断点续传的实现 学 生:叶升路 指导教师:覃 颖 (三峡大学 电气资讯学院) 摘 要:本文介绍了网路下载软体中的最新技术——多执行绪下载和断点续传技术,同时 也介绍了HTTP 协议的发展、特点以及WinSock 程式设计技术。

FTP客户端怎么样实现断点续传的功能?

上传的时候,如果档案已经存在,服务端会返回档案已经存在大小,根据这个大小,从本地档案读取这个大小之后的资料,进行断点续传

c# winform 中怎么利用wini实现断点续传?

WinI 提供对常用的网际网路协议,包括 Gopher、 FTP 和 HTTP 访问。使用 WinI,可以不必处理 WinSock、 TCP/IP 或特定的网际网路协议的详细资讯写入 Inter 客户端应用程式的程式设计中,更高的级别。

FTP 通常公开要将一个档案附加到另一个"追加"命令。WinI 不直接公开此功能。

在 Inter Explorer 3.0 和 4.0 中,这一问题的解决方法是从伺服器下载档案、 将附加到该客户端然后上载该档案备份到伺服器上。

从开始 Inter Explorer 5,FTP 命令可以直接传送到 FTP 伺服器使用 FtpCommand,如下所示:

CHAR szTemp[256]

wsprintf (szTemp, "APPE %s", "DestFile.txt")

bRet = FtpCommand( hConnection, WinI Connection handle

TRUE, Yes, I expect a response

FTP_TRANSFER_TYPE_ASCII, I'm receiving ASCII

szTemp, This is the FTP mand I am passing

0, No context needed

&hResponse)The handle to read the response

if (!bRet)

{

cout <<"FtpCommand failed, error: " <<GetLastError() <<endl

return

}

wsprintf (szTemp, "This data will be appended to the file")

DWORD dwSize

if (!InterWriteFile (hResponse, (LPVOID)szTemp, lstrlen(szTemp)+1, &dwSize))

{

cout <<"InterWriteFile failed, error: " <<GetLastError() <<endl

return

}

用swoole做websocket,怎么实现资料断点续传

在php的web控制器中,每当更新了资料库的资料库后,我需要将这些资料传送到其他使用者的客户端, 不知在web控制器中怎么实现这个一个目的,怎么才能swoole_websocket_server传送这些最新的资料。如果再建立一个 swoole_client话又感觉不好。

主轴定位功能的实现原理是什么

主轴定位指通过一个输出点控制主轴旋转到特定的位置以方便换刀或者主轴配合其它装置动作。

主轴定位是通过主轴伺服驱动模组内建的位置控制功能和检测主轴的位置编码器(可以安装在主轴上或者是主轴电机内建的编码器)来实现主轴定位的。

API有断点续传的功能吗?

有,可以通过HTML5 File api 实现断点续传。

一、实现档案多选

HTML5的<input>新增了"multiple"属性,该属性可接受多个值的档案上传栏位

<input type=file multiple="multiple" name="file"id="file">

添加了该属性使用者就可以在弹出的对话方块中一次性选择多个档案了

二、实现档案从计算机拖拽到网页以及新增档案伫列功能

这里我们用 dragover 和 drop 两个事件来管理档案拖拽的功能

其中 dragover 用来处理在指定的元素上移动时的事件,这里我们通过给body系结dragover时间来处理页面中拖动档案的事件

document.body.addEventListener('dragover', dragFile,false) function dragFile(evt) { evt.sPropagation() evt.preventDefault() evt.dataTransfer.dropEffect = 'copy' }

用 drop 事件来处理滑鼠松开时候的事件,此时应该将使用者拖动过来的档案加入到上传伫列中,以供后续的处理

document.body.addEventListener('drop', dropFile,false) function dragFile(evt) { evt.sPropagation() evt.preventDefault() dataTransfer.files属性可以获取到所有拖动选择的档案,通过遍历可以读取到所有档案的资讯。 遍历每个档案可以获取到档案的 name、size、type、lastModifiedDate等关键资讯 var files = evt.dataTransfer.files addfile 方法 用来新增上传档案伫列,在input的change事件中也需要呼叫 该方法首先检查有无档案正在上传中,如果有就将后续加入的档案放到上传伫列中,如果没有档案正在上传就直接执行上传命令 addfile(files)

}

断点续传指的是在下载或上传时,将下载或上传任务(一个档案或一个压缩包)人为的划分为几个部分,每一个部分采用一个执行绪进行上传或下载,如果碰到网路故障,可以从已经上传或下载的部分开始继续上传下载未完成的部分,而没有必要从头开始上传下载。使用者可以节省时间,提高速度。

360浏览器如何实现断点续传

360安全浏览器内建下载工具是支援断点续传功能的,但是断点续传需要下载工具和下载资源相互支援配合才行。

所以,如果使用360se下载的档案无法断点续传的话,一般都是资源伺服器不支援断点续传功能。

部分下载网为了防止盗链是不允许断点续传的。

代理的实现原理是什么?

代理伺服器有很多种,大体分为三类:HTTP、FTP、SOCKS,其中又分为透明代理和不透明代理,透明代理一般是闸道器,为硬体

过程:

(1)客户端先和代理伺服器通讯,建立TCP连线,目的IP是代理伺服器的IP

(2)客户端发出GET命令,GET命令中包含URL或IP地址、明文

(3)代理伺服器将其中的URL转换为IP地址,可能会有DNS,将源资料包中的资料拷贝下来,去掉URL,重新组包再发出去

(4)代理伺服器和真实伺服器通讯,源IP是代理伺服器的IP

以上就是代理的实现原理,在我们日常生活中只有在学习IT才会了解哦,我也是在黑马程式设计师学习之后才了解的。

什么是ECMP?ECMP的实现原理是什么?

Linux 平台上之 Multipath Routing 应用

--------------------------------------------------------------------------------

撰稿/整理: Rex Tsai <chihchun@kalug.linux.>

HTML 版本:

:kalug.linux./sections.php?op=viewarticle&artid=4

TEXT 版本:

[Tips] Linux 平台上之 Multipath Routing 应用.

$Date: 2001/10/22 09:25:41 $

警告:

*****************************************************************************

您因使用或不能使用本文之教学而产生之任何软体、硬体损害(包括但不限

于直接或间接个人损害、营业利润之丧失、业务中断、营业资讯之遗失、或

任何其他金钱损失),概不负任何损害赔偿责任。

The author has taken care in the preparation of this paper, but

make no expressed or implied warranty of any kind and assume no

responsibility for errors or omissions. No liability is assumed for

incidental or consequential damages in connection with or arising

out of the use of the information or programs contained herein.

Linux is a registered trademark of Linus Torvalds. Other product

and pany names mentioned herein may be the trademarks of their

respective owners.

*****************************************************************************

撰稿/整理: Rex Tsai <chihchun@kalug.linux.>

此档案应有许多技术上得问题. 请熟悉的朋友来信指教.

[Introduction]

许多中小企业或是 Soho 甚至家庭, 会在家中装有一条以上宽频/宽频线路.

这篇 Tips 将介绍如何在 Linux 上, 好好的应用这些资源.

在你使用两家不同的 ISP 的时候, destination address-based load

balancing 将会是最好的解决方案. 你的封包可以即时透过不同的 ISP 线路

走出去. 当然这里所提的是从内部到外部, 如果你的专线提供不同的网路服

务提供给网路上得人存取, 那么接下来所说明的方式不适合您.

此篇文章只能提供内部网路对外的 load sharing.

以下文章以 GNU/Debian, Linux kernel 2.4.12, iproute-20001007-1 为

环境, 所有动作请在主机前面执行.

假设你有两条以上的网际网路资料线路 (xDSL, ISDN, Cable, whatever..),

想充分使用这些线路, 概观来看有三种方式

1. Multiplexing

2. Packet-wise load balancing

3. Destination address-based load balancing,

或称 Equal-Cost MultiPath Routing (ECMP)

稍微解释一下三种方式的不同

1. Multiplexing

Multiplexing, 这个方式提供某些路由器提供 offer-load balancing 或叫

做 load sharing. 这个方式可以让路由器将流量分给不同的外流 ports.

但是会造成每个 port 的传送上约有 30 % 的 overhead. 此外, 每家厂商的

实作都是独一的, 因次你会被锁在特定的解决方案上.

类似的技术是 "bonding" 或是 "multi-link". 这里所提得 Bonding 是一

个标准, 是由 Bandwidth on Demand Interoperability Group (一个大

概有四十个制造商的协会)所提. 已经提交给 American National Standards

Institute TR41.4 group. 这个通常的在于两条资料线路都是接在同一个

点(ISP)上的时候, 因此如果是两条不同 ISP 所提供的线路, 那么就没办法

达到这个目的. 当然, 如果你的 ISP 不提供此项技术服务, 那么也是没辙.

举个例子, 像是 stick multiple ISDN channels. 将几个慢速的线路合成为

快速的一条. 像是 ISDN H.221 规格即用到 inverse multiplexing. 但通常

用于视讯传输而不是电子资料.

2. Packet-wise load balancing:

这个在你可以得到所有的 ISP 协助的时候是可行的, 如果两家 ISP 都愿意

协助将其不同的路由器皆设定到同一个 IP 位址. 那么便可以这么作.

在这个方式中, 你会用到像是 sch_teql (the TEQL scheduler) 来创造一个

virtual device 将你的封包分散在不同的网路介面上.

一般来讲, 如果你是使用两家不同 ISP , 那么你不可以使用这个解决方案.

但, 你 "可以" 将所有的网路封包透过 IPIP or CIPE (Crypto IP Encapsu-

lation) 的方式来解决这个问题. 看看 Linux Kernel 中的 IP: tunneling.

3. Equal-Cost MultiPath:

在 Linux 核心中叫做 equal cost multipath (CONFIG_IP_ROUTE_MULTIPATH)

比较正确的说法应该是 "destination address-based load balancing". 一

般 Linux 想要为某个 IP 位址找到路由, 会因为效能的问题去查验暂存(cache)

中的资料, 如果目标 IP 并没有在暂存空间中, 那么他便会去查 routing table

来决定该 IP 位址的路由, 并将该路由放进 cache 中.

一般来讲核心中的路由功能只能为某个封包决定唯一的方向. 如果使用 ECMP 并

有机会让某个 package pattern 具有好几种不同的方向, 可以让某个符合路由条

件的封包透过 "equal" cost 或是自订的权重来选择该走的路由.

[Howto]

如果你有数台电脑想使用外部网路, 一条 ADSL 不够你使用(例如某人抓档太凶)

那么这是你正在找的解决方案. 你所能做的作好的方式就是每个 connection 可以

以 "non-deterministic fashion" 的方式选择路由, 将 connection 分散到不同的

Router 上, 注意: 这里所说的不是 packets, 这样 TCP/IP session 将无法连续.

但是这整个路由程式有两个部份四个问题要解决.

1a. How to get your packets to the outside world,

1b. How the outside world replies to you,

2a. How the outside world sends packets to you,

2b. How you reply to the outside world.

Multipath 可以解决 1a 出去的问题. 一般的路由设定可以解决 1b 与 2a. 而 2b

则必须使用 policy routing (multiple tables)才能解决, Multiple Tables 可以

让你加入以封包来源位址为依据来决定路由.

以下的范例, 在核心中, 务必加入编译以下选项

必备:

CONFIG_NETLINK=y

这个选项是 Kernel/User link socket

CONFIG_RTNETLINK=y

Routing messages

CONFIG_INET=y

TCP/IP neorking

CONFIG_IP_ADVANCED_ROUTER=y

IP: advanced router

CONFIG_IP_MULTIPLE_TABLES=y

IP: policy routing

CONFIG_IP_ROUTE_MULTIPATH=y

IP: equal cost multipath

选用:

CONFIG_IP_ROUTE_LARGE_TABLES=y

一般来讲 IP: large routing tables 也会勾选, 一方面 routing

zones 可以大于 64 笔, 这些资料存在 hash 资料结构中, 也可以

加速 "the routing process".

而 iproute 套件也是必须的软体. 这个软体的安装方式与位置请洽询提供

您所使用套件之厂商/组织. (Red Hat, Debian, Mandrake, SuSE, etc...)

重头戏来了, 这里假设你有三块网路卡, 分别给内部网路与两家 ISP. eth0

是内部网路, eth1 与 eth2 是其他两家 ISP 线路.

eth0 是内部网路, 范围是 10.0.0.0/255.255.255.0

eth1 其中一家 ISP, IP 是 1.1.1.1, 闸道器(gateway)是 1.1.1.253

eth2 另外一家 ISP, IP 是 2.2.2.2, 闸道器(gateway)是 2.2.2.253

# 列出所有的 rule

ip rule list

# table 后的 "10" 是 table identifer, 为数字.

# 注: 可用英文代称取代请看 /etc/iproute2/rt_tables

#

# table 10 是给在 gateway 后面的内部网路使用, 10.0.0.x 是 LAN 使用的 IP.

#

# pref 后面指定的 "10" 是 priority. 为 policy routing database 搜寻的次序

ip rule add pref 10 to 10.0.0.0/24 table 10

ip route add 10.0.0.0/24 table 10 dev eth1

# table 20 给 ISP #1, IP 1.1.1.1, gateway 1.1.1.253

# pref 后面指定的 "20" 是 priority. 为 policy routing database 搜寻的次序

ip rule add pref 20 from 1.1.1.1 table 20

ip route add default table 20 via 1.1.1.253

# table 30 is for ISP #2, IP 2.2.2.2, gateway 2.2.2.253

ip rule add pref 20 from 2.2.2.2 table 30

ip route add default table 30 via 2.2.2.253

# 列出所有的 rule

ip rule list

# 列出 table 10 的 rule

ip route list table 10

# 列出 table 20 的 rule

ip route list table 20

# If your ISP's have servers that authenticate by originating IP address,

# (e.g. SMTP or NNTP servers) you will want to explicitly list them here.

# 这里是静态的 routing table 设定. 如果你的 ISP 有提供某些网路服务, 必须该

# ISP 的 IP 才能使用, 那么你会想将它设定在这里

# (e.g. Proxy, SMTP or NNTP Server)

ip route add 1.1.1.0/24 dev eth1

ip route add 2.2.2.0/24 dev eth2

# 如果上面所有的 routing table 都没有吻合, 那么封包会走 default route

# 这里使用 "ECMP" 来选择上游路由器.

# "ip route repleace" 是用来取代原本的 default routi.

ip route replace default nexthop via 1.1.1.253 dev eth1 \

nexthop via 2.2.253 dev eth2

# 如果你想加上权重, 是这样使用的. 请依据你的线路网路频宽

# 频宽越大, 请把 weight 加大.

#ip route replace default nexthop via 1.1.1.253 dev eth1 weight 1 \

# nexthop via 2.2.253 dev eth2 weight 3

# Make it all happen. IMPORTANT! The above mands do NOT

# flush the route cache!

ip route flush cache

<-- 结束 -->

Linux 上得 ECMP implementation 的实作有一个特色, 当你的上游网路介面

使用 ARP (e.g. 使用传统 IP-over-Ether)时, 如果其中一个网路介面阵

亡时, Linux kernel 会自动把该介面 "shutdown", 并停止那些需要经过该

介面的 "nexthops". 但是要附注一提的是, 如果你使用的是 "网路型" ADSL

服务, 你会取得一个 ADSL 路由器, 你可能会架设一个 NAT 伺服器与 ADSL

路由器放在同一个 Ether Hub 上, 如果这个时候 ADSL 断线, 但是 Hub

并未断线, Linux 会认为该网路卡仍在 on-line 状态. 除非是该 hub 或是网

路卡故障, kernel 才会 shutdown 该网路介面.

因此如果你需要确实的 "failover", 请动手写一个小 script, 定时用 ping

或称 "icmp echo request" 来询问 ISP 端的闸道器是否正常的运作, 并用

"ip route replace" 来置换那些确定可通的路由. 这里就请您自行处理了.

Enjoy it, Rex.

[Reference]

[1] Linux-Net mailing list. :uwsg.iu.edu/hypermail/linux//

原文 :uwsg.iu.edu/hypermail/linux//0107.3/0028.

[2] Alexey N. Kuzsov, April 14, 1999, IP Command Reference

[Futrher reading]

[1] Jack Coates , Load-Balancing on LRP HOWTO

[2] Netherlabs BV (bert hubert ),

Gregory Maxwell ,

Remco van Mook ,

Martijn van Oosterhout ,

Paul B Schroeder ,

Jasper Spaans , howto@ds9a.nl,

Linux 2.4 Advanced Routing Howto

[3] Horacio J. Pe?a, horape@pendium..ar, 05/Apr/2000

Policy based routing MICRO-HOWTO,

:pendium..ar/policy-routing.txt

[Keywords]

Linux, Routeing, 路由, ADSL, 宽频, 宽频, 频宽, 合并, 分流, 共用

[Acknowledgements]

Zygo Blaxell (zblaxell@furryterror.) 在 Linux- 的说明

Digital Sesame, Inc - :d11e. 提供环境测试.

--

Best Regards.

Rex Tsai <chihchun_at_kalug.linux.>

--

ThinkPHP 的 C 函式实现原理是什么?

c方法里面有个静态变数,每次初始化的时候就把配置赋值给这个静态变数,然后每次使用的时候就直接在这个静态变数里获取了,楼主应该知道静态变数在整个执行期间都存在吧