* 断点续传文件下载线程
*/
public class BreakDownloadThread extends Thread {
long[] startPos, endPos;
SplitDownloadThread[] childThreads;
long fileLength;
boolean firstDown = true;
File tempFile;
DataOutputStream output;
String mUrl;
String filePath, fileName;
boolean stopped =false;
public BreakDownloadThread(String url, String filePath, String fileName, int splitCount) {
this.mUrl = url;
this.filePath = filePath;
this.fileName = fileName;
tempFile = new File(filePath + File.separator + fileName + ".dat");
if (tempFile.exists()) {
firstDown = false;
readPos();
} else {
startPos = new long[splitCount];
endPos = new long[splitCount];
}
}
@Override
public void run() {
try {
if (firstDown) {
fileLength = getFileSize();
if (fileLength == -1) {
System.err.println("File Length is not known!");
} else if (fileLength == -2) {
System.err.println("File is not access!");
} else {
for (int i = 0; i < startPos.length; i++) {
startPos[i] = (long) (i * (fileLength / startPos.length));
}
for (int i = 0; i < endPos.length - 1; i++) {
endPos[i] = startPos[i + 1];
}
endPos[endPos.length - 1] = fileLength;
}
}
childThreads = new SplitDownloadThread[startPos.length];
for (int i = 0; i < startPos.length; i++) {
childThreads[i] = new SplitDownloadThread(i, mUrl, filePath + File.separator + fileName, startPos[i], endPos[i]);
childThreads[i].start();
}
boolean breakWhile = false;
while (!stopped) {
writePos();
Thread.sleep(500);
breakWhile = true;
for (int i = 0; i < startPos.length; i++) {
if (!childThreads[i].downOver) {
breakWhile = false;
break;
}
}
if (breakWhile) break;
}
System.out.println("文件下载结束!");
} catch (Exception e) {
e.printStackTrace();
}
}
public long getFileSize() {
int nFileLength = -1;
try {
URL url = new URL(mUrl);
HttpURLConnection httpConnection = (HttpURLConnection) url.openConnection();
int responseCode = httpConnection.getResponseCode();
if (responseCode >= 400) {
return -2;
}
String sHeader;
for (int i = 1; ; i++) {
sHeader = httpConnection.getHeaderFieldKey(i);
if (sHeader != null) {
if (sHeader.equals("Content-Length")) {
nFileLength = Integer.parseInt(httpConnection.getHeaderField(sHeader));
break;
}
} else
break;
}
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
return nFileLength;
}
private void writePos() {
try {
output = new DataOutputStream(new FileOutputStream(tempFile));
output.writeInt(startPos.length);
for (int i = 0; i < startPos.length; i++) {
output.writeLong(childThreads[i].startPos);
output.writeLong(childThreads[i].endPos);
}
output.close();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
private void readPos() {
try {
DataInputStream input = new DataInputStream(new FileInputStream(tempFile));
int nCount = input.readInt();
startPos = new long[nCount];
endPos = new long[nCount];
for (int i = 0; i < startPos.length; i++) {
startPos[i] = input.readLong();
endPos[i] = input.readLong();
}
input.close();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
public class SplitDownloadThread extends Thread {
String mUrl;
long startPos, endPos;
int threadID;
boolean stopped = false, downOver = false;
RandomAccessFile accessFile;
public SplitDownloadThread(int threadID, String url, String name, long startPos, long endPos) throws IOException {
this.threadID = threadID;
this.mUrl = url;
this.startPos = startPos;
this.endPos = endPos;
accessFile = new RandomAccessFile(name, "rw");
accessFile.seek(startPos);
}
@Override
public void run() {
while (startPos < endPos && !stopped) {
try {
URL url = new URL(mUrl);
HttpURLConnection httpConnection = (HttpURLConnection) url.openConnection();
String sProperty = "bytes=" + startPos + "-";
httpConnection.setRequestProperty("RANGE", sProperty);
InputStream input = httpConnection.getInputStream();
byte[] b = new byte[1024];
int nRead;
while ((nRead = input.read(b, 0, 1024)) > 0 && startPos < endPos && !stopped) {
startPos += write(b, 0, nRead);
}
downOver = true;
} catch (Exception e) {
e.printStackTrace();
}
}
}
public synchronized int write(byte[] b, int nStart, int nLen) {
int n = -1;
try {
accessFile.write(b, nStart, nLen);
n = nLen;
} catch (IOException e) {
e.printStackTrace();
}
return n;
}
}
}