⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 httpdown.java

📁 该软件用java开发
💻 JAVA
字号:
/**
 * Http下载协议,支持多任务多线程,能自动识别重名的文件,智能地对要下载的重名的文件进行重命名,
 * 保证不会对硬盘原先的文件造成损失;本程序还能自动创建多级文件夹,能保证当下载时的保存目录不存在时也能正确下载;
 */

/**
 * @author king、dfl
 * @version V1.1
 */
import java.net.*;
import java.io.*;

// HTTP下载方式
public class HttpDown
{
	public HttpDown(String fileURL, String savePath)
	{
		this.downFielURL = fileURL; // 可以是任何的文件类型
		this.savePath = savePath;
		this.ctrlThread = new ControlThread();  // 新建一个控制线程
		this.ctrlThread.run();
				
	}
	public HttpDown(String fileURL, String savePath,int threadNum)
	{
		this.downFielURL = fileURL; // 可以是任何的文件类型
		this.savePath = savePath;
		this.downThreadNum = threadNum;
		this.ctrlThread = new ControlThread();  // 新建一个控制线程
		this.ctrlThread.run();
				
	}

	private class DownThread extends Thread // 数据下载的线程
	{
		private long start; // 每个下载线程对象开始下载的起始位置

		private long end; // 每个下载线程对象下载结束时的 文件位置

		private boolean stop = false; // 该线程对象是否暂停

		private int tryTimes = 20; // 尝试连接的次数 假如为负数的话说明没有限制
		private long readCount = 0;
		public DownThread(long offset, long end)
		{
			this.start = offset;
			this.end = end;
		}

		public void run()
		{
			int httpStatusCode = 0;// 服务器返回的状态值
			
			// 这里开始向服务器请求数据  将要服务器返回的数据保存到文件
			System.out.println(savePath +" in DownThread");
			try
			{
				
				int readNum;
				byte buf[] = new byte[4096];

				conn = url.openConnection();
				HttpURLConnection httpconn = (HttpURLConnection) conn;
				httpconn.setRequestProperty("User-Agent", "NetFox");
				System.out.println("~ first " + start + " end  " + end);
				httpconn.setRequestProperty("RANGE", "bytes=" + start + "-");
				httpconn.setRequestProperty("GET", url.getFile() + " HTTP/1.1");
				httpconn.setRequestProperty("Accept",
						"image/gif,image/x-xbitmap,application/msword,*/*");
				httpconn.setRequestProperty("Connection", "Keep-Alive");

				//DataInputStream br=new DataInputStream( httpconn.getInputStream());
				InputStream inStream = httpconn.getInputStream();
				RandomAccessFile rafrw = new RandomAccessFile(savePath, "rw");
				rafrw.seek(start);
				readNum = inStream.read(buf);
				System.out.println("qq " + (end - start + 1));
				if (readNum > (int) (end - start + 1)) 
					readNum = (int) (end - start + 1);
				while (readCount < (end - start + 1) && readNum != -1)
				{
					setTotalReadCount(readNum);
					readCount = readCount + readNum;
					rafrw.write(buf, 0, readNum);
					//  System.out.println("q"+i);
					readNum = inStream.read(buf);
					if (readCount > (int) (end - start + 1))  /////////// 这是什么?
						readCount = (int) (end - start + 1);
				}
				if(totalReadNum <  fileLen) // 测试用
					System.out.println("DownLoad Error. len "+fileLen+" readCount "+readCount);
				else
				{
					hasFinished = true;
				}
				rafrw.close();
				inStream.close();
				System.out.println("exit in Download Thread.");
			}
			catch (IOException e)
			{
				System.out.println(e);
			}
		}
		public synchronized  void setTotalReadCount(long readnum)
		{
			totalReadNum += readnum;
		}
	}
	
	private class ControlThread extends Thread //线程控制类
	{
		
		public ControlThread()
		{
			try
			{
				url = new URL(downFielURL);
				
			}
			catch (Exception e)
			{
				System.out.println(e.getMessage());
			}
		}

		public void run()
		{
			// 在这里可以假如是否要增加线程
			try
			{
				conn = url.openConnection();
				//conn.connect();
				fileLen = conn.getContentLength(); //得到要下载的文件的长度
			}
			catch (Exception e)
			{
				e.getMessage();
			}
			System.out.println(savePath + "  保存路径");
			File savefile =new File(savePath);  
			String parentPath = new String (savefile.getParentFile().toString());// 测试 保存的目录是否存在
			System.out.println(parentPath + "  parentPath");
			File parent = new File(parentPath);
			if(!parent.exists()) // 当要保存的文件目录不存在时 创建文件目录
			{
				System.out.println("文件目录不存在。");
				if(parent.mkdirs())
					System.out.println("   创建文件夹成功。");
				else
					System.out.println("   创建文件夹失败。");
			}
			if(!savefile.exists())  // 文件不存在时 创建一个文件
			{
				System.out.println("文件名没有重复,可以创建该文件。");
				try
				{
					savefile.createNewFile();
				}
				catch (IOException e)
				{
					// TODO 自动生成 catch 块
					e.printStackTrace();
				}
			}
			// 当所要保存的文件名存在时 在文件名后加上(1)等 
			else{
				int jd_i = 1;
				String jd_name;
				String jd_savepath;
				while(true)
				{
					jd_name = getOKName(savefile.getName(),jd_i);
					jd_i++;
					jd_savepath = savefile.getParentFile().toString()+"\\"+jd_name;
					System.out.println(jd_savepath + " in Control Thread");
					File jk_file = new File(jd_savepath);
					if(!jk_file.exists())  // 文件不存在时 创建一个文件
					{
						System.out.println("文件名没有重复,可以创建该文件。");
						try
						{
							jk_file.createNewFile();
							savePath = new String(jd_savepath);
							break;
						}
						catch (IOException e)
						{
							// TODO 自动生成 catch 块
							e.printStackTrace();
						}
					}
				}
			}
			
			System.out.println("Len of fiel in ControlThread " + fileLen);
			long jd_block = fileLen/downThreadNum;
			
			int c_1;  
			long j_2=0;
			long j_3;
		    for(c_1=0;c_1<downThreadNum;c_1++)
		    {
		         if(c_1==downThreadNum)
		        	 j_3=fileLen-1;
		         else 
		        	 j_3=j_2+jd_block;
				 DownThread downThread = new DownThread(j_2, j_3);
				 downThread.start();
				 
		         j_2=j_3+1;
		    }
		}

	}
	public static String getOKName(String filename,int num) 
	{
		String reName;
        if ((filename != null) && (filename.length() > 0)) 
		{
            int i = filename.lastIndexOf('.');
			System.out.println(i +" the value of i ." );
            if ((i > 0) && (i <= (filename.length() - 1)))
			{ // 文件名正常
            	reName = filename.substring(0,i)+"("+num+")"+filename.substring(i);
                return reName;
            }
			else if(i == 0) // 说明第一个字符就是 "."
			{
				reName = "("+num+")"+filename;
				return reName;
			}
			else // 没有找到 字符 "."
			{
				reName = filename+"("+num+")";
				return reName;
			}
        }
		return ("("+num+")");
    }
	public long getTotalReadNum()
	{
		return this.totalReadNum;
	}
	public boolean getHasFinished()
	{
		return hasFinished;
	}
	public long getFileLength()
	{
		return fileLen;
	}
	
	private String downFielURL;
	
	ControlThread ctrlThread;

	private URL url;

	private URLConnection conn; // 

	private String savePath; // 文件的保存路径
	
	private int downThreadNum = 3; // 下载线程数量 至少一个线程 默认为 3个线程

	private long fileLen; // 要下载的文件总长度

	private boolean hasBegin = false; // 是否已经正确连接并且 开始下载
	
	private boolean hasFinished = false; // 判断下载是否结束
	
	private long totalReadNum = 0;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -