📄 download.java
字号:
import java.io.*;
import java.net.*;
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
public class Download extends Frame
{
private File fileOut;
private URL url;
private long fileLength;
private int ThreadNum; //初始化线程数
//private Label l1 = new Label("请输入下载地址:"); //创建标签L1
private TextField tf1 = new TextField(); //创建文本域tf1长度为30
//private Label l2 = new Label("请输入需要的线程:"); //创建标签L2
private TextField tf2 = new TextField(); //创建tf2 输入线程
private TextField tf3 = new TextField(); //创建tf3 保存地址
static TextArea ta = new TextArea(); //创建文本区ta
private Button b = new Button();
//private Panel p = new Panel();
public Download()
{
Panel pSave=new Panel();
pSave.add(new Label("请输入保存地址"));
pSave.add(tf3=new TextField(25));
//tf1.setColumns(50);
Panel pDown=new Panel();
pDown.add(new Label("请输入下载地址"));
pDown.add(tf1=new TextField(25));
//tf2.setColumns(50);
Panel pXian=new Panel();
pXian.add(new Label("请输入所需线程"));
pXian.add(tf2=new TextField(5));
//tf3.setColumns(10);
Panel pLeft=new Panel();
pLeft.setLayout(new GridLayout(3,1));
pLeft.add(pDown);
pLeft.add(pSave);
pLeft.add(pXian);
Panel pCenter=new Panel();
ta=new TextArea(80,30);
pCenter.setLayout(new BorderLayout());
pCenter.add(pLeft,BorderLayout.WEST);
pCenter.add(ta,BorderLayout.EAST);
Panel pBtn=new Panel();
pBtn.add(b=new Button("下载")); //创建按钮
pCenter.add(pBtn,BorderLayout.SOUTH);
this.add(pCenter);
this.setTitle("多线程下载软件");
this.setSize(600,300);
this.setLocation(280,280);
pLeft.setBackground(Color.white); //设定面板的背景颜色为白色
pBtn.setBackground(Color.white);
pCenter.setBackground(Color.white);
ta.append("下载过程显示"+"\n\n");
this.setVisible(true);
//给b注册监听器
b.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
try{
String str = tf1.getText();
ThreadNum = Integer.valueOf(tf2.getText()); //把字符串变量转换为整形变量
String str2 =tf3.getText();
String info=new String();
long[] startPos; //设置起始位置
long[] endPos; //设置结束位置
long[] xPos; //设置读取字节
int i ,y;
//初始化
startPos=new long[ThreadNum];
endPos=new long[ThreadNum];
xPos=new long[ThreadNum];
System.out.println(str);
System.out.println("正在链接URL");
ta.append("正在链接URL\n");
//构造URL链接
/*在构建了URL后,调用它的函数openConnection()返回一个HttpURLConnection实例,
用getContentLength实现获取远程文件的长度,
然后调用getResponseCode()返回HTTP的响应状态码,
状态小于400就表示正常,返回大于400的,比如401就表示服务器
不正常了,返回小于零的,比如-1则表示无法获知文件大小。*/
url=new URL(str);
HttpURLConnection urlcon=(HttpURLConnection)url.openConnection();
fileLength=urlcon.getContentLength();
printMIME(urlcon); //打印信息
System.out.println("下载文件大小为"+fileLength/1024+"K");
ta.append("下载文件大小为"+fileLength/1024+"K"+"\n\n");
//设置连接信息
if(urlcon.getResponseCode()>=400)
{
System.out.println("服务器响应错误");
System.exit(-1);
}
if(fileLength<=0)
System.out.println("无法获知文件大小");
else
{
//设置线程显示
long threadLength=fileLength/ThreadNum;
for(i=0;i<ThreadNum;i++)
{
startPos[i]=threadLength*i;
xPos[i]=threadLength;
xPos[ThreadNum-1]=fileLength-threadLength*(ThreadNum-1); //多线程正常读取字节
endPos[i]=threadLength*i+xPos[i];
y=i+1;
System.out.println("第"+y+"线程从第"+startPos[i]+"个字节开始读取"+xPos[i]+"个字节");
ta.append("第"+y+"线程从第"+startPos[i]+"个字节开始读取"+xPos[i]+"个字节"+"\n");
System.out.println("线程:"+y+"下载范围:"+startPos[i]+"--"+endPos[i]);
ta.append("线程:"+y+"下载范围:"+startPos[i]+"--"+endPos[i]+"\n");
//获取URL,转变成字符串赋值给trueurl
String trueurl=urlcon.getURL().toString();
//获取文件名,substring截取'/'后的
String filename=trueurl.substring(trueurl.lastIndexOf('/')+1);
//设置保存位置
fileOut=new File(str2,filename);
}
}
}
catch(IOException ie)
{
System.err.println(ie);
}
init();
}
}
);
//对窗口监听,使其可以正常关闭
this.addWindowListener(new WindowAdapter()
{
public void windowClosing(WindowEvent e)
{
System.exit(0);
}
}
);
}
private void init()
{
Threads [] down = new Threads[ThreadNum]; //启动一组子线程
try
{
for(int i=0;i<ThreadNum;i++)
{
RandomAccessFile randOut=new RandomAccessFile(fileOut,"rw");
randOut.setLength(fileLength);
long threadLength=fileLength/ThreadNum; //每个线程长度
randOut.seek(threadLength*i); //用于移动文件指针到指定的位置
down[i]=new Threads(url,randOut,threadLength,i+1); //引用线程类对象
down[i].setPriority(10); //设置优先级为10
down[i].start(); //启动新创建的线程
}
//循环判断是否下载完毕
boolean flag=true;
while (flag)
{
//等待下载过程结束
Threads.sleep(1000); //调用Thread类的sleep()方法使线程在指定的时间内处于休眠,设为休眠1秒
flag = false;
for (int i = 0; i < ThreadNum; i++) //检测是否每条线程都已经完成
if (!down[i].isFinished())
{
flag = true;
break;
}
}// end while
System.out.println("文件下载完毕,保存在"+fileOut.getPath() );
ta.append("文件下载完毕,保存在"+fileOut.getPath()+"\n\n");
}
catch (FileNotFoundException e)
{
System.err.println(e);
e.printStackTrace();
}
catch(IOException e)
{
System.err.println(e);
e.printStackTrace();
}
catch (InterruptedException e) //抛出异常,唤醒睡眠
{
System.err.println(e);
}
}
/*显示相关信息
这里调用了getHeaderFieldKey方法,返回第i个文件头的索引键值。
然后以返回的mine为参数调用了getHeaderField方法,返回第i个
文件头的实际值,也就是文件长度。调用MIME显示下载对象的相关信息。*/
private void printMIME(HttpURLConnection http)
{
for(int i=0;;i++)
{
String mine=http.getHeaderField(i);
if(mine==null)
return;
System.out.println(http.getHeaderFieldKey(i)+":"+mine);
ta.append(http.getHeaderFieldKey(i)+":"+mine);
ta.append("\n\n");
}
}
public static void main(String[] args)
{
Download app=new Download();
}
} //结束
//线程类
class Threads extends Thread
{
private InputStream randIn;
private RandomAccessFile randOut;
private URL url;
private long threadLength;
private int ThreadId; //子线程ID
private boolean done=false; //文件传输完成标志
public Threads(URL url,RandomAccessFile out,long threadLength,int ThreadId)
{
this.url=url;
this.randOut=out;
this.threadLength=threadLength;
this.ThreadId=ThreadId;
}
public void run()
{
try
{
HttpURLConnection http=(HttpURLConnection)url.openConnection();
//设置开始位置
http.setRequestProperty("Range","bytes="+threadLength*(ThreadId-1)+"-");
randIn=http.getInputStream();
//请求传输开始的位置
}
catch(IOException e)
{
System.err.println(e);
}
byte [] buffer=new byte[1024];
int offset;
long localSize=0;
System.out.println("线程"+ThreadId+"开始下载");
Download.ta.append("线程"+ThreadId+"开始下载\n");
try
{
while ((offset = randIn.read(buffer))>0&&localSize<=threadLength)
{
randOut.write(buffer,0,offset);
localSize+=offset; //下一次开始写的位置
}
randOut.close();
randIn.close();
done=true;
System.out.println("线程"+ThreadId+"完成下载");
Download.ta.append("线程"+ThreadId+"完成下载\n");
this.interrupt();
}
catch(Exception e)
{
System.err.println(e);
}
}
public boolean isFinished()
{
return done;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -