import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import com.Ostermiller.util.Base64;
public class MuliThreadBreakPointDown {
private String path = "http://apache.mirror.phpchina.com/struts/source/struts-2.0.11.1-src.zip";
private static int ARRAY_LEN=1024;
private int threadCount = 1;
private ThreadDownLoadData[] downs = new ThreadDownLoadData[threadCount];
private String outputFilePath ="c:/struts.zip";
private String outputConfigPaht = "c:/struts.txt";
private long [] beginBorders = new long[threadCount];
private boolean hasProxy = true ;
class MyHttpInputStream {
private InputStream inputStream;
private long beginBorder ;
private void getRemoteInputStream() {
try {
URL url = new URL(path);
HttpURLConnection httpUrl = (HttpURLConnection) url.openConnection();
if ( hasProxy )
setHttpProxy(httpUrl);
httpUrl.setRequestProperty("RANGE", "bytes=" + beginBorder + "-"); //这是很关键地方
inputStream = httpUrl.getInputStream();
} catch (Exception e) {
e.printStackTrace();
}
}
public InputStream getInputStream() {
getRemoteInputStream();
return inputStream;
}
public void setInputStream(InputStream inputStream) {
this.inputStream = inputStream;
}
public long getBeginBorder() {
return beginBorder;
}
public void setBeginBorder(long beginBorder) {
this.beginBorder = beginBorder;
}
}
class ThreadDownLoadData extends Thread {
private InputStream inputStream;
private long beginBorder;
private long endBorder ;
private RandomAccessFile writeDiskrandomFile ;
public ThreadBreakPointMsg threadBreakPointMsg ;
private int threadNo ;
public ThreadBreakPointMsg getThreadBreakPointMsg() {
return threadBreakPointMsg;
}
public void setThreadBreakPointMsg(ThreadBreakPointMsg threadMsg) {
this.threadBreakPointMsg = threadMsg;
}
public int getThreadNo() {
return threadNo;
}
public void setThreadNo(int threadIndex) {
this.threadNo = threadIndex;
}
public InputStream getInputStream() {
return inputStream;
}
public void setInputStream(InputStream inputStream) {
this.inputStream = inputStream;
}
public long getBeginBorder() {
return beginBorder;
}
public void setBeginBorder(long beginBorder) {
this.beginBorder = beginBorder;
}
public long getEndBorder() {
return endBorder;
}
public void setEndBorder(long endBorder) {
this.endBorder = endBorder;
}
public void run () {
if ( inputStream != null )
{
try {
RandomAccessFile randmsg =threadBreakPointMsg.getRandomThreadMsgFile() ;
byte[] b= new byte[ARRAY_LEN];
int arrayIndex = 0;
while ( (beginBorder< endBorder) && ( (arrayIndex = inputStream.read(b, 0, b.length) )!=-1 ) )
{
writeDiskrandomFile.seek(beginBorder);
if ( (beginBorder + arrayIndex) > endBorder ){
writeDiskrandomFile.write(b,0, (int)(endBorder - beginBorder) );
arrayIndex = (int)(endBorder - beginBorder);
} else
writeDiskrandomFile.write(b,0,arrayIndex );
beginBorder=beginBorder + arrayIndex ;
Long seekIndex = threadBreakPointMsg.getSeekAxis().get( threadNo );
randmsg.seek( seekIndex );
String str = randmsg.readLine();
if ( str != null ) {
int length = str.length();
String newStr = "thread["+ (threadNo+1) +"]=" + beginBorder ;
length = length -newStr.length();
String space = "";
for(int i=0;i< length ; i++){
space = space + " ";
}
newStr = newStr + space + "/r/n";
byte[] datas2 = newStr.getBytes();
randmsg.seek( seekIndex );
randmsg.write(datas2, 0, datas2.length); //回写已下载的位置
}
}
int counter = 0;
for(int i=0;i<downs.length;i++) {
if ( downs[i].getState().toString().equalsIgnoreCase("TERMINATED") ) {
counter = counter + 1;
}
}
if ( counter== (threadCount-1)) {
writeDiskrandomFile.close();
randmsg.close();
inputStream.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
public RandomAccessFile getWriteDiskrandomFile() {
return writeDiskrandomFile;
}
public void setWriteDiskrandomFile(RandomAccessFile randomFile) {
this.writeDiskrandomFile = randomFile;
}
}
public void deal () {
File outConfigFile = new File(outputConfigPaht);
File outDataFile = new File(outputFilePath);
RandomAccessFile randomThreadMsgFile = null;
RandomAccessFile randomFile = null;
try {
randomThreadMsgFile = new RandomAccessFile(outConfigFile,"rw");
randomFile = new RandomAccessFile(outDataFile,"rw");
} catch (FileNotFoundException e) {
e.printStackTrace();
}
ThreadBreakPointMsg threadMsg = new ThreadBreakPointMsg();
threadMsg.setThreadCount(threadCount);
threadMsg.setRandomThreadMsgFile(randomThreadMsgFile);
boolean isBreakFlag = false ;
try {
if ( !outConfigFile.exists() || (outConfigFile.length()==0 ))
threadMsg.createThreadBreakPointMsg();
else {
threadMsg.initThreadBreakPointMsg();
isBreakFlag = true ;
}
} catch (Exception e) {
e.printStackTrace();
}
long fileSize = getFileSize();
long averageSize = fileSize/threadCount;
long counter = fileSize - averageSize ;
for(int i=0;i<threadCount;i++) {
downs[i] = new ThreadDownLoadData();
MyHttpInputStream myInputStream = new MyHttpInputStream();
if ( isBreakFlag ) {
if ( beginBorders[i] ==0 ){
downs[i].setBeginBorder(fileSize - (counter+averageSize) );
}
else {
myInputStream.setBeginBorder(beginBorders[i]);
}
}
else {
downs[i].setBeginBorder(fileSize - (counter+averageSize) );
}
myInputStream.setBeginBorder(downs[i].getBeginBorder());
downs[i].setInputStream( myInputStream.getInputStream());
if ( i< (threadCount-1)){
downs[i].setEndBorder( fileSize - counter);
}
else {
downs[i].setEndBorder( fileSize );
}
System.out.println("downs["+i+"]"+downs[i].getEndBorder() );
downs[i].setWriteDiskrandomFile(randomFile);
downs[i].setThreadBreakPointMsg(threadMsg);
downs[i].setThreadNo(i);
counter = counter - averageSize;
}
for(int i=0;i<threadCount;i++){
downs[i].start();
}
}
private void setHttpProxy(HttpURLConnection httpUrl ) {
System.getProperties().put( "http.proxyPort", "8080");
System.getProperties().put( "http.proxyHost", "192.168.0.1");
System.getProperties().put( "http.proxySet", "true" );
httpUrl.setRequestProperty( "Proxy-Authorization", "Basic " + Base64.encode( "yourName" + ":" + "yourKey" ) );
}
public long getFileSize( ){
int fileLength=-1;
try
{
URL url=new URL(path);
HttpURLConnection httpUrl=(HttpURLConnection) (url.openConnection());
if ( hasProxy )
setHttpProxy(httpUrl);
int responseCode=httpUrl.getResponseCode();
if(responseCode>=400)
{
System.out.println("Web服务器响应错误");
return -2;
}
String sHeader;
for(int i=1;;i++)
{
sHeader=httpUrl.getHeaderFieldKey(i);
if(sHeader!=null)
{
if(sHeader.equals("Content-Length"))
{
fileLength=Integer.parseInt(httpUrl.getHeaderField(sHeader));
break;
}
}
else
{
break;
}
}
}
catch (Exception ex)
{
ex.printStackTrace();
}
return fileLength;
}
class ThreadBreakPointMsg {
private int threadCount;
private RandomAccessFile randomThreadMsgFile;
private List<Long> seekAxis = new ArrayList<Long>();
public RandomAccessFile getRandomThreadMsgFile() {
return randomThreadMsgFile;
}
public void setRandomThreadMsgFile(RandomAccessFile randomThreadMsgFile) {
this.randomThreadMsgFile = randomThreadMsgFile;
}
public void createThreadBreakPointMsg() {
try {
byte[] datas = ("threadCount=" + threadCount + "/r/n").getBytes();
randomThreadMsgFile.seek(0);
randomThreadMsgFile.write(datas, 0, datas.length);
Long seekIndex = new Long(datas.length);
for (int i = 0; i < threadCount; i++) {
seekAxis.add(seekIndex);
randomThreadMsgFile.seek(seekIndex);
byte[]datas2 = ("thread["+(i+1)+"]=0 /r/n").getBytes();
randomThreadMsgFile.write(datas2, 0, datas2.length);
seekIndex = seekIndex + datas2.length;
}
} catch (IOException e) {
e.printStackTrace();
}
}
public void initThreadBreakPointMsg() {
try {
randomThreadMsgFile.seek(0);
String line = randomThreadMsgFile.readLine();
byte[] datas = (line +"/r/n").getBytes();
Long seekIndex = new Long(datas.length);
for (int i = 0; i < threadCount; i++) {
seekAxis.add(seekIndex);
line = randomThreadMsgFile.readLine();
int position = line.indexOf("=")+1;
beginBorders[i] = Long.parseLong(line.substring(position,line.length()).trim() );
byte[] datas2 = (line+"/r/n").getBytes();
seekIndex = seekIndex + datas2.length;
}
} catch (IOException e) {
e.printStackTrace();
}
}
public int getThreadCount() {
return threadCount;
}
public void setThreadCount(int threadCount) {
this.threadCount = threadCount;
}
public List<Long> getSeekAxis() {
return seekAxis;
}
public void setSeekAxis(List<Long> seekAxis) {
this.seekAxis = seekAxis;
}
}
public static void main(String[] args) throws Exception {
MuliThreadBreakPointDown main = new MuliThreadBreakPointDown();
main.deal();
}
}