时间:2021-05-21
最近在给我的开源下载框架Aria增加FTP断点续传下载和上传功能,在此过程中,爬了FTP的不少坑,终于将功能实现了,在此把一些核心功能点记录下载。
FTP下载原理
FTP单线程断点续传
FTP和传统的HTTP协议有所不同,由于FTP没有所谓的头文件,因此我们不能像HTTP那样通过设置header向服务器指定下载区间。
但是FTP协议提供了一个更好用的命令REST用于从指定位置恢复任务,同时FTP协议也提供了一个命令SIZE用于获取下载的文件大小,有了这两个命令,FTP断点续传也就没有什么问题。
FTP断点续传的原理和HTTP的断点续传原理差不多,在暂停时记录文件的停止位置,再次下载时,先读取记录的位置,如果位置存在,则通过REST命令告诉服务器从指定区间进行下载。
FTP多线程断点续传
多线程下载的原理和HTTP多线程下载的原理差不多。先获取文件大小,然后根据线程数,对整个文件进行分段下载,在任务停止时,记录每一条线程的暂停位置,重新开始下载,每一条线程读取对应的下载记录,然后每一线程从指定位置开始下载。
分段下载
和HTTP所不同的是,FTP并没有提供文件区间的API,因此,FTP在分段下载中,只有起始位置而没有结束位置。
因此,你需要在指定位置手动停止线程。
功能实现
本文使用将采用apache commons-net实现FTP断点续传下载\上传功能。<br>
通过下文的几步操作,你就能很简单的实现FTP断点续传。
登录
FTP协议和HTTP协议有所不同,使用FTP进行下载时,你需要进行登录操作。
当然,如果你服务器没有登录功能,你可以忽略登录操作。
FTPClient client = new FTPClient();client.connect(serverIp, port); //连接到FTP服务器client.login(userName, passsword);通过上面三行代码,就可以很简单的登录到FTP服务器上。
在进行登录后,还需要验证是否登录成功
int reply = client.getReplyCode();if (!FTPReply.isPositiveCompletion(reply)) { client.disconnect(); Log.d(TAG, "无法连接到ftp服务器,错误码为:" + reply); return; }由于FTP协议中,连接成功的状态有多个,因此需要通过FTPReply.isPositiveCompletion(reply)用于验证是否成功连接到FTP服务器。
文件信息获取
在连接到FTP服务器后,就需要开始获取下载最重要的几个参数(文件长度、文件名)。
客户端可以通过client.listFiles(remotePath)获取FTP服务器上该路径的文件列表。
如果你的文件为英文名,并且路径中没有中文,那么通过上述代码,便可以获取到正确的文件信息。
但如果FTP上的服务器上的文件名有中文或路径有中文,那么上述代码,你将获取不到正确的文件信息。
正确的写法
由于FTP服务器默认的编码是ISO-8859-1,因此,客户端在获取文件信息时
通过以上代码,便可以获取到正确的文件信息。
文件下载
配置每条线程的下载区间
long fileLength = mEntity.getFileSize();Properties pro = CommonUtil.loadConfig(mConfigFile);int blockSize = (int) (fileLength / mThreadNum);int[] recordL = new int[mThreadNum];for (int i = 0; i < mThreadNum; i++) { recordL[i] = -1;}int rl = 0;for (int i = 0; i < mThreadNum; i++) { long startL = i * blockSize, endL = (i + 1) * blockSize; Object state = pro.getProperty(mTempFile.getName() + "_state_" + i); if (state != null && Integer.parseInt(state + "") == 1) { //该线程已经完成 if (resumeRecordLocation(i, startL, endL)) return; continue; } //分配下载位置 Object record = pro.getProperty(fileName + "_record_" + i); //如果有记录,则恢复下载 if (record != null && Long.parseLong(record + "") >= 0) { Long r = Long.parseLong(record + ""); mConstance.CURRENT_LOCATION += r - startL; Log.d(TAG, "任务【" + mEntity.getFileName() + "】线程__" + i + "__恢复下载"); startL = r; recordL[rl] = i; rl++; } else { recordL[rl] = i; rl++; } //最后一个线程的结束位置即为文件的总长度 if (i == (mThreadNum - 1)) endL = fileLength; //创建分段线程 AbsThreadTask task = createSingThreadTask(i, startL, endL, fileLength); if (task == null) return; mTask.put(i, task);}startSingleTask(recordL);在上面的代码中,主要做了两步操作:
FTP 分段线程区间自动停止
由于FTP协议没有区间下载的原因,为了让线程只下载特定区间的内容,需要客户端在单条线程累计读的数据长度已经超过了所分配的区间长度的时候,停止该条线程。
client.enterLocalPassiveMode(); //设置被动模式 client.setFileType(FTP.BINARY_FILE_TYPE); //设置文件传输模式 client.setRestartOffset(mConfig.START_LOCATION); //设置恢复下载的位置 client.allocate(mBufSize); is = client.retrieveFileStream(new String(remotePath.getBytes(charSet), SERVER_CHARSET)); //发送第二次指令时,还需要再做一次判断 reply = client.getReplyCode(); if (!FTPReply.isPositivePreliminary(reply)) { client.disconnect(); fail(mChildCurrentLocation, "获取文件信息错误,错误码为:" + reply, null); return; } file = new BufferedRandomAccessFile(mConfig.TEMP_FILE, "rwd", mBufSize); file.seek(mConfig.START_LOCATION); byte[] buffer = new byte[mBufSize]; int len; while ((len = is.read(buffer)) != -1) { //如果该条线程读取的数据长度大于所分配的区间长度,则只能读到区间的最大长度 if (mChildCurrentLocation + len >= mConfig.END_LOCATION) { len = (int) (mConfig.END_LOCATION - mChildCurrentLocation); file.write(buffer, 0, len); progress(len); break; } else { file.write(buffer, 0, len); progress(len); } }这里还有几个坑需要处理一下:
关于FTP文件上传
FTP 文件断点续传的方式原理和下载的都差不多:
而和下载有区别的是:
最终效果
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。
学习了多线程下载,而且可以断点续传的逻辑,线程数量可以自己选择,但是线程数量过多手机就承受不起,导致闪退,好在有断点续传。步骤写在了代码的注释里。大概就是获取服
本文为大家分享了实现断点续传下载的具体代码,供大家参考,具体内容如下1、基于Ok+Rxjava实现断点续传下载2、基于Ok+Rxjava+Retrofit实现断
本文所要讲的是Android断点续传的内容,以实例的形式进行了详细介绍。一、断点续传的原理其实断点续传的原理很简单,就是在http的请求上和一般的下载有所不同而
本文实例为大家分享了java断点续传下载的代码,供大家参考,具体内容如下1.Java代码//实现文件下载功能publicStringdownloadFile()
Axel是Linux下一个不错的HTTP/FTP高速下载工具。支持多线程下载、断点续传,且可以从多个地址或者从一个地址的多个连接来下载同一个文件。适合网速不给力