1.多线程分片上传原理
2.断点上传和下载的原理
3.取消上传的原理
4.文件上传下载加密
5.文件合法性和完整性验证
文件下载的流程:
1.得到文件的大小,名字,md5
2.分块,验证每一块的md5
3.断线下载数据库记录
4.合法验证
1. 断点续传原理
在本地下载过程中要使用数据库实时存储到底存储到文件的哪个位置了,这样点击开始继续传递时,才能通过HTTP的GET请求中的setRequestProperty()方法可以告诉服务器,数据从哪里开始,到哪里结束。同时在本地的文件写入时,RandomAccessFile的seek()方法也支持在文件中的任意位置进行写入操作。同时通过广播将子线程的进度告诉Activity的ProcessBar。
---------------------
使用多线程的好处:使用多线程下载会提升文件下载的速度。那么多线程下载文件的过程是:
(1)首先获得下载文件的长度,然后设置本地文件的长度。
HttpURLConnection.getContentLength();//获取下载文件的长度
RandomAccessFile file = new RandomAccessFile("QQWubiSetup.exe","rwd");
file.setLength(filesize);//设置本地文件的长度
(2)根据文件长度和线程数计算每条线程下载的数据长度和下载位置。
如:文件的长度为6M,线程数为3,那么,每条线程下载的数据长度为2M,每条线程开始下载的位置如下图所示。
例如10M大小,使用3个线程来下载,
线程下载的数据长度 (10%3 == 0 ? 10/3:10/3+1) ,第1,2个线程下载长度是4M,第三个线程下载长度为2M
下载开始位置:线程id*每条线程下载的数据长度 = ?
下载结束位置:(线程id+1)*每条线程下载的数据长度-1=?
(3)使用Http的Range头字段指定每条线程从文件的什么位置开始下载,下载到什么位置为止,
如:指定从文件的2M位置开始下载,下载到位置(4M-1byte)为止
代码如下:HttpURLConnection.setRequestProperty("Range", "bytes=2097152-4194303");
(4)保存文件,使用RandomAccessFile类指定每条线程从本地文件的什么位置开始写入数据。
RandomAccessFile threadfile = new RandomAccessFile("QQWubiSetup.exe ","rwd");
threadfile.seek(2097152);//从文件的什么位置开始写入数据
多线程结合断点续传下载
多线程无非是将待下载的文件分成若干个部分进行下载并实现断点续传。
1.同样,我们首先要获取待下载的文件的长度,用来为每个线程分配下载长度。通过HttpURLConnection.getContentLength()获取待下载的文件的长度。如下:
filesize=connection.getContentLength();
2.通过前面获取的下载文件的长度,为每个线程计算下载长度,即为每个线程设置下载的起始位置跟结束位置。通过HttpUrlConnection.setRequestProperty("Range", "bytes=" + 开始位置+ "-" + "结束位置")方法。如下图所示:
[图片上传失败...(image-f5634c-1521193484969)]
计算方法如下:
int block = (filesize % threadCount == 0) ? filesize / threadCount : filesize / threadCount + 1;
所以每个线程对应的起始位置跟结束位置分别为:**i block, (i + 1) block(i从0开始)
3.通过RandomAccessFile可以在文件指定位置写入数据。如下:
mRandomAccessFile.seek(startPos)
4.为每个线程的下载的进度都保存数据,这样每次每次暂停后重新下载都重新读取下载进度,并且可以从上次位置重新下载。并且再本地文件中继续读入数据。
在MyThread中,通过info.getStart() + info.getNow()设置开始下载的位置,如果是第一次下载两个数将都是0,如果是暂停后再下载,则info.getNow()会取出非0值,该值来自数据库存储。使用setRequestProperty告知服务器从哪里开始传递数据,传递到哪里结束,本地使用RandomAccessFile的seek()方法进行数据的本地存储。使用广播将进度的百分比传递给Activity,Activity再改变ProcessBar进行UI调整。
这里很关键的一点是在用户点击暂停后会在Service中调用downLoadUtil.isPause = true,因此上面while循环会结束,停止下载并通过数据库的update()保存进度值。从而在续传时取出该值,重新对服务器发起文件起始点的下载任务请求,同时也在本地文件的相应位置继续写入操作。本文原创,转载请注明出处为SEU_Calvin的博客。
最后补充一点,(17/4/11被面试问到了)关于断线续传的HTTP状态码并不是200,而是206,即HttpStatus.SC_PARTIAL_CONTENT。
---------------------
代码如下:
@Override
@Override
public void run() {
HttpURLConnection conn = null;
RandomAccessFile raf = null;
try {
//连接网络文件
URL url = new URL(mFileInfo.getUrl());
conn = (HttpURLConnection) url.openConnection();
conn.setConnectTimeout(3000);
conn.setRequestMethod("GET");
int length = -1;
if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) {
//获得文件长度
length = conn.getContentLength();
}
if (length <= 0) {
return;
}
//在本地创建文件
File dir = new File(DOWNLOAD_PATH);//验证下载地址
if (!dir.exists()) {
dir.mkdir();
}
File file = new File(dir, mFileInfo.getFileName());
raf = new RandomAccessFile(file, "rwd");//r:读权限,w:写权限,d:删除权限
//设置文件长度
raf.setLength(length);
mFileInfo.setLength(length);
mHandler.obtainMessage(MSG_INIT, mFileInfo).sendToTarget();
} catch (Exception e) {
e.printStackTrace();
} finally {
conn.disconnect();
try {
raf.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
问题:
1.断点上传需要客户端支持吗?
2.知道下载链接,就可以下载,安全问题!
切片上传
https://blog.csdn.net/u011368551/article/details/81531880
demo地址: