通常断点续传指在都是应用在网络文件传输中,由于网络中断或其它原因导致文件需要重新传输,这时候只需要从最后中断前已读取的文件内容开始续传即可。我在这里省去了网络这一环节,全是本地操作。
断点续传原理非常简单:在传输过程中,每次写入内容至目标文件时,都需要记录一下文件流的offset即可。当下次程序重新启动后,读取这个offset值,再从offset的地方继续transfer。
这里我用c#简单写了一个程序来模拟断点续传
1:
2:
3: static int offset = 0; //save the stream position for dest file
4: static void Transfer()
5: {
6: string src = @"f:\test\src.txt";
7: string dest = @"f:\test\dest.txt";
8:
9: try
10: {
11: using (FileStream fout = new FileStream(src, FileMode.Open, FileAccess.Read))
12: {
13: //only read 10 bytes
14: byte[] bout = new byte[10];
15: fout.Read(bout, 0, 10);
16:
17: using (FileStream fin = new FileStream(dest, FileMode.Open, FileAccess.Write))
18: {
19: //write 10 bytes to file
20: fin.Write(bout, 0, bout.Length);
21: offset = bout.Length;
22: //simulate break,in the real environment ,it may be network error,power off etc.
23: throw new ArgumentException("break write");
24:
25: }
26: }
27: }
28: catch (ArgumentException ex)
29: {
30: Console.WriteLine(ex.Message);
31: }
32:
33: //continue write,only for test
34: using (FileStream fout = new FileStream(src, FileMode.Open, FileAccess.Read))
35: {
36: if (offset > 0)
37: {
38: //note: the key point for file continue transfer
39: fout.Seek(offset, SeekOrigin.Begin);
40: }
41: byte[] bout = new byte[1024];
42: fout.Read(bout, 0, bout.Length);
43:
44: using (FileStream fin = new FileStream(dest, FileMode.Append, FileAccess.Write))
45: {
46: fin.Write(bout, 0, bout.Length);
47: }
48: }
49: }
注释都在代码里,不多解释了,这里存在一个问题,我是采用一个varible来save stream position的,现在很多ftp工具或都下载工具都不是这么做的。更好的做法是再读取一次未传输(下载)完成的文件来得到这个position即可,还有稍微复杂的是,不必读取整个文件来计算这个position,可以把这值写到file header中去,再解析一下file header即可,这个有点类似于http协议中的HEAD命令。