web开发中多线程下载文件

</pre><pre name="code" class="html">web开发中涉及到多线程下载文件,源代码如下:
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.URL;


/*
 * 多线程下载的测试类
 */
public class Demo {
	public static int threadCount = 3 ;
	public static int runningThread = 3 ;
	
	
	public static void main(String[] args) throws Exception {
		//1·连接服务器,获取一个文件,获取文件的长度,在本地创建一个大小跟服务器文件一样大的临时文件
		//模拟服务器的文件可以放在本地server的webapps/Root文件夹下,文件最好是.exe程序!
		String path = "http://211.87.234.10:8080/drivethelife.exe" ;
		URL url = new URL(path) ;
		HttpURLConnection conn = (HttpURLConnection) url.openConnection() ;
		conn.setConnectTimeout(5000) ;
		//大小写敏感
		conn.setRequestMethod("GET") ;
		int code = conn.getResponseCode() ;
		if(code == 200){
			//服务器返回的数据长度,实际上是文件的长度
			int length = conn.getContentLength() ;
			System.out.println("文件总长度length==>"+length) ;
			//使用API 在本地创建一个大小跟服务器端文件一样大小的临时文件  第一个参数是文件名,第二个是mode模式
			RandomAccessFile raf = new RandomAccessFile("drivethelife.exe", "rwd") ;
			//指定创建文件的长度
			raf.setLength(length) ;
			raf.close() ;
			//假设是3个线程去下载资源
			//平均每个线程下载的文件大小
			int blockSize = length / threadCount ;
			System.out.println("blockSize==>"+blockSize) ;
			for(int threadId=1; threadId<=threadCount; threadId++){
				int startIndex = (threadId-1)*blockSize ;
				int endIndex = threadId*blockSize - 1 ;
				if(threadId == threadCount){//最后一个线程下载的长度要稍微长一点
					endIndex = length ;
				}
				System.out.println("线程:"+threadId+"下载:--"+startIndex+"--->"+endIndex) ;
				new DownloadThread(path, threadId, startIndex, endIndex).start() ;
			}
			
			
		}else{
			System.out.println("服务器错误") ;
		}
		
	}
	
	
	/*
	 * 下载文件的子线程  每一个线程下载对应位置的文件
	 */
	public static class DownloadThread extends Thread{
		private int threadId ;
		private int startIndex ;
		private int endIndex ;
		private String path ;
		/**
		 * @param path 下载文件在服务器上的路径
		 * @param threadId 线程id
		 * @param startIndex 线程下载开始位置
		 * @param endIndex 线程下载的结束位置
		 */
		public DownloadThread(String path, int threadId, int startIndex, int endIndex) {
			super();
			this.path = path ;
			this.threadId = threadId;
			this.startIndex = startIndex;
			this.endIndex = endIndex;
		}

		@Override
		public void run() {
			try {
				//检查是否存在记录下载长度的文件,如果存在则读取这个文件的数据并添加到startIndex。
				File tempFile = new File(threadId+".txt") ;
				if(tempFile.exists()&&tempFile.length()>0){
					FileInputStream fis = new FileInputStream(tempFile) ;
					byte[] temp= new byte[1024] ;
					int leng = fis.read(temp) ; //fis的输入流读到temp中去
					String downloadLen = new String(temp,0,leng) ;
					int downloadlenInt = Integer.parseInt(downloadLen) ;
					startIndex = downloadlenInt ; //修改下载的真实的开始位置
					fis.close() ;
				}
				
				URL url = new URL(path) ;
				HttpURLConnection conn = (HttpURLConnection) url.openConnection() ;
				conn.setRequestMethod("GET") ;
				//请求服务器下载部分的文件   指定文件的位置。
				//若需要下载特定长度的资源,则需要HTTP请求头字段Range去设置  !!
				conn.setRequestProperty("Range", "bytes="+startIndex+"-"+endIndex) ;
				System.out.println("线程真实下载:"+threadId+"下载:--"+startIndex+"--->"+endIndex) ;
				conn.setConnectTimeout(5000) ;
				int code = conn.getResponseCode() ;//若是从服务器请求全部资源 200 OK 如果请求部分资源 206 OK
				System.out.println("code==>"+code) ;
				if(code == 206){
					InputStream is = conn.getInputStream() ;//若前面没有设置Range.返回全部资源,已经设置了请求的位置,返回的是当前位置对应的文件的输入流
					
					//输出到本地文件的对应位置   使用java API RandomAccessFile  使用指针指定到对应位置,然后下载
					RandomAccessFile raf = new RandomAccessFile("drivethelife.exe", "rwd") ;
					//随机写文件的时候从哪个位置开始写
					raf.seek(startIndex) ;//定位文件
					int len = 0;
					byte[] buffer = new byte[10240000] ;
					int total = 0 ;//已经下载的数据长度
					while((len=is.read(buffer))!=-1){
						RandomAccessFile file = new RandomAccessFile(threadId+".txt","rwd") ;//记录当前线程下载的数据长度
						raf.write(buffer, 0, len) ;
						total +=len ;
						file.write(String.valueOf(total+startIndex+"").getBytes()) ;//记录的是下载的位置.
						file.close() ;
					}
					is.close() ;
					raf.close() ;
					System.out.println("线程:"+threadId+"下载完毕了。。。") ;
				}else{
					System.out.println("线程:"+threadId+"下载失败。。。") ;
				}
				
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} finally{
				runningThread -- ;
				if(runningThread==0){
					//所有线程执行完毕
					for(int i=1; i<=3; i++){
						File file = new File(i+".txt") ;
						file.delete() ;
					}
					System.out.println("文件下载完毕,并删除所有的下载记录") ;
				}
			}
		}
	}
}


你可能感兴趣的:(多线程,web开发,下载)