一种基于分片的断点续传方法的实现

2023-12-09 02:55唐文军隆承志
电子设计工程 2023年23期
关键词:分片服务端服务器端

唐文军,隆承志

(1.华南理工大学信息网络工程研究中心,广东广州 510641;2.华南理工大学计算机科学与工程学院,广东 广州 510006)

文件上传是在线学习平台中一个使用非常频繁的功能,教师提交课件、学生交作业等,都需要用到文件上传的功能。文件上传功能大多采用单进程模式实现,这种上传方式实现起来比较简单,但在实际应用中存在几个方面的问题[1-5]:1)在服务器和网络带宽资源不够的情况下,会因为内存溢出或网络阻塞导致上传失败;2)在上传较大的文件时会占用过多资源,导致浏览器甚至电脑没有响应,影响用户体验;3)上传失败后,之前上传的字节流将全部抛弃,必须全部重新上传,极大地影响上传效率。针对文件上传的以上痛点问题,提出了一种基于分片的文件断点续传方法,对需上传的文件按照一定的规则进行分片,并结合多线程,提高上传效率,同时采用断点续传的方式,解决上传失败后要全部重新上传的问题。

1 常用的文件上传方法

文件上传的方式一般分为简单文件上传和文件断点续传两种[6]。简单文件上传是指用户通过客户端(如浏览器)将文件传输到服务器进行保存,在传输过程中,服务器不保存文件上传的状态,如果传输过程中出现任何问题造成文件传输中止,文件需要重新传输。文件断点续传是指在使用文件断点续传服务时,服务端实时保存文件的上传状态,当用户主动中止上传或者其他原因导致文件上传中止后再次上传该文件时,系统无需从头开始上传,会从上一次上传中止处开始传输数据。

简单文件上传的特点是流程简单、容易实现,前后端只需很少的交互操作就能够完成文件的传输和保存等工作。但简单文件上传的缺点也比较明显,当用户上传较大的文件,所需时间比较长时,上传过程中出现任何问题,都可能导致上传失败,当用户重新上传时,仍需要从文件头部开始上传,不仅会造成网络带宽的浪费,且严重影响用户体验[7]。

文件断点续传的基本原理就是在文件上传过程中,定时或者实时保存文件的上传状态[8-9]。传输过程中保存文件上传状态有两种方法:第一种是记录文件已上传的字节数,文件上传被中止时,服务器端可以通过读取临时目录中上传文件的字节数来获取上传的进度,当用户再次发起上传时,服务器端可以从客户端的请求中读取文件名、文件长度和文件MD5 值等参数[10-11],获取文件的上传进度,并通知客户端从服务端返回的字节处开始文件传输,直到文件传输完毕;第二种是将大文件按一定规则分片,逐个将文件分片传输到服务端进行保存,当文件传输被中止时,服务端只损失正在上传的分片,已上传的分片不受影响,当用户再次上传时,服务器端从客户端请求中获取上传的文件信息,根据文件信息查询该文件已上传的分片记录并返回给客户端,客户端根据服务器端的信息解析分片记录并上传的未上传的文件分片[12]。

通过对于基于字节数的断点续传算法和基于分片的断点续传算法的原理介绍可以发现基于字节数的断点续传算法的优点在于原理简单、便于实现,缺点是功能扩展性差。基于分片的断点续传算法在继承了基于字节数的断点续传算法优点的同时,还能根据实际应用需求进行功能扩展,如为了发挥服务器多核CPU 的优势[13],可以在基于分片上传的基础上采用多线程上传模式,启动多个线程同时上传多个分片。同时,基于分片的断点续传算法容错性较强[14],当用户在首次上传和二次上传期间,对文件做过修改,使用基于字节数的断点续传算法方法,服务端无法判断文件是否经过修改,如果是对已上传部分的内容做的修改,那么文件是没有意义的,用户无法接受。如果使用基于分片的断点续传算法,在用户修改过文件之后,二次上传时,服务端可以检测每个已上传分片的MD5,如果发现两次上传的分片MD5 值不一致,则重传该分片即可[15-16],保证了文件传输的正确性和可靠性。

2 断点续传中的分片方法设计

基于分片的断点续传方法的关键问题是确定分片的大小。分片的大小对文件传输和存储的的效率影响很大。文件分片过小会导致分片过多,增加上传过程中的分片校验负担和传输完成后分片重组的开销;但如果分片过大,分片上传的时间较长,且在上传过程中出现任何问题造成该分片上传不成功,则需要重传该分片,失去了断点续传的优势。

分片的大小一般通过实验获取,我校学习平台的云存储系统所用的Linux 系统磁盘采用ext4 格式,其磁盘块(block)的大小是4 kB,通过对比测试,分片大小的设置为4 kB 的整数倍时,存储效率相对较高,其主要原因是无论传输过程中的分片写入,还是上传完后的分片重组,每一次I/O 都是写入和读取磁盘中整数倍的Block 块,能有效提高I/O 的性能,对学习平台中2 000 余份学生作业和近200 份教师课件文件的大小和频率进行统计,如图1 所示。

图1 学习平台上传文件大小分布图

在学习平台中,10~100 MB 之间的文件占总上传数的一半左右,所以选取的分片大小为4 MB,即每一个完整的分片都能够写满Linux 系统的1 024 个节点,在提升磁盘使用率和IO 性能的前提下,不会因为分片过多造成分片合并时消耗过多资源,在具体实现时,为了提高性能,8 MB 以下的文件不做分片处理。

文件分片总数N的计算公式如下:

其中,fileSize 是文件大小,segmentSize 是预设的分片大小。分片上传状态用一个bit 数组保存,其中每一位的值代表该序号的片段的上传状态,0 表示未上传,1 表示已上传。如数组{0,1,1,0,0,1,0,1,1}表示正在上传的文件分为9 个片段,其中第2、3、6、8、9 个片段已上传到服务器,第1、4、5、7 个片段还未上传成功。

服务器端负责更新并保存上传状态数组,直到文件传输完毕,客户端按分片顺序计算出分片的起止位置,并从文件中读取这一段文件内容上传到服务器,如传输因故中止重新上传时,从服务器获取上传状态记录,并解析出未上传分片序号。每个文件分片的起止位置计算公式如下:

其中,Sx和Ex分别是第x个片段的起始和结束位置。

3 基于分片的断点续传方法的设计和实现

3.1 分片上传前端实现

基于分片的断点续传方法前端实现使用百度WebFE(FEX)团队开发的一个基于HTML5 的开源JS项目WebUploader。WebUploader 封装了文件分片、多线程并发、文件MD5 生成和校验、上传进度显示等基础功能,前端开发只需要在初始化WebUploader组件时将相关参数注入即可,基于分片的断点续传方法的前端关键代码如图2 所示。

图2 前端实现关键代码

create 方法负责使用传入的参数初始化WebUploader 组件,传入参数是JSON 格式文本,其中:

server:指定服务器端对应处理文件上传的接口;

chuncked:设置前端是否采用分片上传方式;

chunckSize:设置文件分片大小,根据上一节的分析,文件分片大小设置为4 MB;

treads:设置文件上传时同时启动的并发线程数,考虑到性能问题,该参数设置为3,即同时启动三个线程。

为实现文件秒传功能,前端必须计算并上传文件的MD5 值到服务器端,用户在重复上传文件时,服务器端会根据上传的文件MD5 值进行判断,如果已上传文件中存在同样MD5 值,则表示该文件已经上传过,可以直接提示用户上传成功。通过测试发现,大文件的MD5 值计算非常消耗资源,为提高计算效率,在fileQueued 函数中,只将待上传的文件名和文件尺寸组合hash,作为该文件的MD5 值。

3.2 分片上传服务器端实现

服务器端接口采用Java SpringBoot 框架实现,Java 提供了专门处理文件分片随机读取的类,即RandomAccessFile(随机访问文件)类。该类是Java中功能最为丰富的文件访问类,提供了众多的文件访问方法。RandomAccessFile 类支持对文件的随机访问方式,可以跳转到文件的任意位置处读写数据。在访问一个文件时,不必把文件从头读到尾,而是可以像访问数据库一样随意地访问一个文件的某个部分。

基于分片的断点续传方法服务器端关键代码如图3 所示。

图3 服务器端关键代码

其中,checkFileMd5 方法用于检验当前请求上传的文件在服务器上是否存在,并返回其状态;uploadFile 方法负责将上传的分片保存在临时目录;mergeFile 方法负责将文件分片合并。Controller层维持一个已上传分片列表,记录已经上传的分片信息,并依次循环调用这三个接口,直至文件上传完成。

服务器端处理文件分片上传的逻辑如下:

1)服务器端收到上传请求后,获取文件MD5值,调用接口checkFileMd5,查询该MD5 是否已经存在,如果存在,且文件传输状态为已完成,则提示用户文件已上传,即实现了文件秒传功能;

2)如果MD5 值存在,但文件传输状态为未完成,则获取已上传分片列表,返回所有还没上传分块的编号,前端进行条件筛算出哪些没上传的分块,然后进行上传,即实现断点续传功能;

3)如果MD5 值不存在,表示该文件是第一次上传,则创建临时目录存放分片信息,每一次接收到分片时,判断当前分片所属的文件的所有分片是否已经传输完毕,如果已传输完成,则开始合并文件并转移完整文件到目的目录,并删除临时目录,通知用户文件传输成功。

4 实验分析

将简单文件上传和基于分片的断点续传方法进行对比测试。测试网络环境是校内千兆网络,正常上行带宽为8~10 MB/s,测试服务器是虚拟化服务器,CPU32核,内存为32 GB,硬盘空间为1 T,操作系统为CenterOS7,客户端是个人电脑,CPU4核,Intel Core i7,内存为16 GB,使用Chrome 浏览器进行上传测试。

考虑到学习平台的实际运行情况,该次测试使用简单文件上传方法、不同分片大小和不同线程的断点续传方法分别对四个不同大小的文件(4.1、53、102、511 MB)进行上传,对比其上传效率,每个组合分别上传三次,取其平均上传时间(s),测试结果如表1 所示。

表1 测试结果

通过文件上传测试可知,文件秒传和断点续传的功能都已实现,从表1 可知,由于分片上传相比简单文件多了前端分片、MD5 值计算和服务器端合并分片等步骤的开销,单线程模式下,不论分片大小,各种尺寸的文件传输效率都低于简单文件上传模式,在多线程模式下,分片尺寸4 MB 的上传效率要显著高于分片尺寸2 MB,但分片尺寸的继续增长对上传效率的提高影响不大。

5 结论

文中提出基于分片的断点续传方法,前端使用百度提供的开源项目WebUpload 组件,服务器端使用SpringBoot框架,利用Java提供的RandomAccessFile类实现文件的读取和合并,该方法已在华南理工大学特色专业在线学习平台上部署并运行,有效地提高了文件上传的效率和可靠性。

猜你喜欢
分片服务端服务器端
上下分片與詞的時空佈局
分片光滑边值问题的再生核方法
Linux环境下基于Socket的数据传输软件设计
CDN存量MP4视频播放优化方法
基于模糊二分查找的帧分片算法设计与实现
云存储中基于相似性的客户-服务端双端数据去重方法
新时期《移动Web服务端开发》课程教学改革的研究
浅析异步通信层的架构在ASP.NET 程序中的应用
在Windows Server 2008上创建应用
基于Qt的安全即时通讯软件服务器端设计