前言:
今天了解了一下断点续传,先记录一下,可能了解的不是特别全面,主要是看网上的实现。
正文:
根据了解其主要实现是两种吧,一种是
断点续传可以通过使用RandomAccessFile(随机访问文件)专门处理文件的类,里面有seek方法和skipBytes()方法可以移动文件指针具体,可以自行了解,另外也可以使用InputStream,里面有一个skip方法可以移动文件指针。实现思路就是每次传输时用缓冲区,每次写入记录当前已经传输的大小,然后保存,暂停时将记录和对应文件永久保存(数据库,文件等)。下次传输时用seek或者skip函数移动指针再读取传输。
关于RandomAccessFile
“r”:以只读的方式打开,调用该对象的任何write(写)方法都会导致IOException异常
“rw”:以读、写方式打开,支持文件的读取或写入。若文件不存在,则创建之。
“rws”:以读、写方式打开,与“rw”不同的是,还要对文件内容的每次更新都同步更新到潜在的存储设备中去。这里的“s”表示synchronous(同步)的意思
“rwd”:以读、写方式打开,与“rw”不同的是,还要对文件内容的每次更新都同步更新到潜在的存储设备中去。使用“rwd”模式仅要求将文件的内容更新到存储设备中,而使用“rws”模式除了更新文件的内容,还要更新文件的元数据(metadata),因此至少要求1次低级别的I/O操作。
关于skip和seek:
调用seek方法类定位大于文件长度的位置将导致IOException,与java.io.InputStream的skip()不同,seek可以定位到文件的任意位置,而skip只能相对于当前位置定位到另一个位置。seek方法是一个相对高开销的操作,需慎重使用,较好使用流数据来构建应用的访问模式。(摘自网络)
下面是两种模拟实现的代码,具体实现可以参考,之后尽量自己写一个javaweb的简单实现
博客1:使用的skip实现
博客2:使用的seek实现
第一种
/**
* 测试实现文件断点续存
* 使用seek函数
* @author ht032
*
*/
public class TestFile {
public static void main(String[] args) {
// TODO Auto-generated method stub
// File file = new File("d:/1.txt");
// File file = FileManage.CreateDir("d:/user.txt");
// FileManage.remove("d:/dir1");
try {
int len = new TestFile().CopyFile("d:/lenet80.png", "d:/temp.png", 67584);
System.out.print("已经上传:"+len/1024.0);
System.out.println("KB\n"+len);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private RandomAccessFile sourceFile;
private RandomAccessFile targetFile;
/**
* 实现复制,需要首先设置source目标文件流
*
* @param target 目标文件
* @param position 源文件的起始位置
* @return 返回当前已经传输的文件大小
*/
public int CopyFile(String source, String target, long position) throws Exception {
if (source == null)
throw new Exception("source is null!");
byte[] buff = new byte[1024];
int len = 0;
try {
// 打开文件
targetFile = new RandomAccessFile(target, "rw");
sourceFile = new RandomAccessFile(source, "r");
//文件指针移动到指定位置
sourceFile.seek(position);
targetFile.seek(position);
long length = sourceFile.length();
System.out.printf("文件总大小%.2fKB\n", length / 1024.0);
while (true) {
// int read = rafilein.read(buff);
int read = sourceFile.read(buff);
targetFile.write(buff);
len += read;
if (len >= length/2 ||read<0)
break;
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
// 打开日志文件
// FileWriter log=new FileWriter(logPath);
// log.write(str);
try {
sourceFile.close();
targetFile.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return len;
}
}
第二种
package FileDemo;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.RandomAccessFile;
public class TestFile2 {
public static void main(String[] args) {
// TODO Auto-generated method stub
try {
int len = new TestFile2().CopyFile("d:/lenet80.png", "d:/temp.png", 11264);
System.out.print("已经上传:"+len/1024.0);
System.out.println("KB\n"+len);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private InputStream sourceFile;
//这里客户端模拟续存也可使用RandomAccessFile
// private RandomAccessFile targetFile;
private OutputStream targetFile;
/**
* 实现复制,需要首先设置source目标文件流
* 使用skip
* @param target 目标文件
* @param position 源文件的起始位置
* @return 返回当前已经传输的文件大小
*/
public int CopyFile(String source, String target, long position) throws Exception {
if (source == null)
throw new Exception("source is null!");
byte[] buff = new byte[1024];
int len = 0;
try {
// 打开文件,在后面追加 实现断点续存
targetFile = new FileOutputStream(target,true);
sourceFile = new FileInputStream(source);
//文件指针移动到指定位置
sourceFile.skip(position);
// long length = sourceFile.length();
// System.out.printf("文件总大小%.2fKB\n", length / 1024.0);
while (true) {
// int read = rafilein.read(buff);
int read = sourceFile.read(buff);
targetFile.write(buff);
len += read;
if(
read<0
//leng>4*1024//先传输4KB
)
break;
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
// 打开日志文件
// FileWriter log=new FileWriter(logPath);
// log.write(str);
try {
sourceFile.close();
targetFile.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return len;
}
}