精华内容
下载资源
问答
  • java swing url下载器

    2018-07-01 20:42:17
    基于java swing的url下载器 可见博客:https://blog.csdn.net/hunjue0915/article/details/80877155
  • 前期的入库筛选工作已经由url管理器完成了,整理的工作自然要由url下载器接手。当我们需要爬取的数据已经去重后,下载器的主要任务的是这些数据下载下来。所以它的使用也并不复杂,不过需要借助到我们之前所学过的一...
  • java URL 下载器实例

    2011-12-09 15:14:51
    自己制作的URL下载器,可以做个例子给大家用,里面是一个多线程的java下载器,方便大家的学习
  • java url下载器

    2018-07-01 20:41:09
    正好数学题目做的不想做了,就自己撸了一个url下载器出来。因为没花多少时间,做的比较简单,主要功能就加了一个进度条,在这里记一下,以后要是闲着没事干再改进。运行效果截图:界面UI:package View; import tool...

    最近在一些学校的官网上看考研大纲的时候,发现很多学校官网上面的资源是直接用a标签指向的,似乎是因为没有加download属性,还是文件比较小,没法下载下来。正好数学题目做的不想做了,就写了一个url下载器出来。因为没花多少时间,做的比较简单,主要功能就加了一个进度条,在这里记一下,以后要是闲着没事干再改进。

    运行效果截图:


    界面UI:

    package View;
    
    import tool.FileSave;
    import tool.WindowUtil;
    
    import javax.swing.*;
    import javax.swing.border.EmptyBorder;
    import java.awt.*;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.awt.event.WindowAdapter;
    import java.awt.event.WindowEvent;
    
    /**
     * @author yb
     */
    public class MainView extends JFrame {
        /**
        * 文件存放地址按钮,开始按钮
         * */
        private JButton filechoose,start;
        /**
        * url输入框
        * */
        private JLabel notice;
        private TextField url,name;
        private String savepath;
        private JProgressBar progressBar;
        public static void main(String[] args) {
            EventQueue.invokeLater(new Runnable() {
                @Override
                public void run() {
                    try {
                        UIManager
                                .setLookAndFeel("com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel");
                        MainView mainView = new MainView();
                        mainView.setVisible(true);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            });
        }
        public MainView(){
            initview();
        }
    
        private void initview() {
            this.setTitle("url文件下载器");
            setBounds(0, 0, 700, 500);
            WindowUtil.center(this);
            setResizable(false);
    
            JPanel contentPane = new JPanel();
            contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
            contentPane.setBackground(new Color(224, 223, 223));
            setContentPane(contentPane);
            contentPane.setLayout(null);
            setLocationRelativeTo(null);
    
            JPanel featurepel = new JPanel();
            featurepel.setBounds(0, 0, 700, 500);
            featurepel.setBackground(new Color(238, 239, 239));
            contentPane.add(featurepel);
            featurepel.setLayout(null);
    
            filechoose=new JButton("选择存放目录");
            filechoose.setHorizontalAlignment(SwingConstants.LEFT);
            filechoose.setFont(new Font("黑体", Font.PLAIN, 20));
            filechoose.setBounds(20, 240, 150, 40);
            featurepel.add(filechoose);
    
            start=new JButton("下载");
            start.setHorizontalAlignment(SwingConstants.LEFT);
            start.setFont(new Font("黑体", Font.PLAIN, 20));
            start.setBounds(190, 240, 80, 40);
            featurepel.add(start);
    
            JLabel title = new JLabel("输入url地址(带http/https)");
            title.setFont(new Font("黑体", Font.PLAIN, 20));
            title.setBounds(20, 10, 300, 40);
            featurepel.add(title);
    
            url=new TextField();
            url.setFont(new Font("黑体", Font.PLAIN, 20));
            url.setBounds(20, 60, 580, 40);
            featurepel.add(url);
    
            JLabel namelable = new JLabel("文件重命名");
            namelable.setFont(new Font("黑体", Font.PLAIN, 20));
            namelable.setBounds(20, 120, 200, 40);
            featurepel.add(namelable);
    
            name=new TextField(20);
            name.setFont(new Font("黑体", Font.PLAIN, 20));
            name.setBounds(20, 180, 200, 40);
            featurepel.add(name);
    
            JLabel process = new JLabel("进度");
            process.setFont(new Font("黑体", Font.PLAIN, 20));
            process.setBounds(20,300,580,40);
            featurepel.add(process);
    
            progressBar=new JProgressBar();
            progressBar.setFont(new Font("黑体", Font.PLAIN, 20));
            progressBar.setBounds(20,350,580,40);
            progressBar.setForeground(Color.BLUE);
            featurepel.add(progressBar);
    
            notice=new JLabel();
            notice.setFont(new Font("黑体", Font.PLAIN, 20));
            notice.setBounds(20,410,580,40);
            featurepel.add(notice);
            setAction();
        }
    
        private void setAction() {
            // 定义关闭按钮事件
            this.addWindowListener(new WindowAdapter() {
                @Override
                public void windowClosing(WindowEvent e) {
                    System.exit(0);
                }
            });
            filechoose.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    JFileChooser choose = new JFileChooser();
                    choose.setAcceptAllFileFilterUsed(false);
                    choose.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY );
                    choose.showOpenDialog(null);
                    savepath= choose.getSelectedFile().getPath();
                }
            });
            start.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    notice.setText("");
                    progressBar.setValue(0);
                    String filename=name.getText();
                    String fileurl=url.getText();
                    if (filename.equals("")||fileurl.equals("")){
                        JOptionPane.showMessageDialog(null,"Url或名称为空");
                    }else {
                        FileThread thread = new FileThread(filename, fileurl);
                        thread.start();
                    }
                }
            });
        }
        class FileThread extends Thread{
            private String fileurl,filename;
            public FileThread(String name,String url) {
                this.fileurl=url;
                this.filename=name;
            }
    
            @Override
            public void run(){
                FileSave.saveFile(progressBar,savepath,fileurl,filename,notice,name,url);
            }
        }
    
    
    }
    

    文件下载工具类

    package tool;
    
    import javax.swing.*;
    import java.awt.*;
    import java.io.File;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.net.HttpURLConnection;
    import java.net.URL;
    import java.net.URLConnection;
    /**
    * 文件保存工具类
     * */
    public class FileSave  {
        public static void saveFile(JProgressBar jProgressBar, String path, String url, String name, JLabel notice, TextField namelable, TextField urllable){
    
            FileOutputStream fos = null;
            try {
                //创建URL对象并指定所对应的地址。
                URL download = new URL(url);
                URLConnection conn = download.openConnection();
                Long connLength=conn.getContentLengthLong();
                ProgressBar pbt = new ProgressBar(connLength,jProgressBar,notice);
                //建立输入流获取url的数据。
                InputStream is = download.openStream();
                //建立文件输出流来存储资源。
                int n=url.lastIndexOf(".");
                String type=url.substring(n,url.length());
                String newpath=path+"/"+name+type;
                newpath = newpath.replaceAll("\\\\", "/");
                fos = new FileOutputStream(newpath);
                new Thread(pbt).start();
                int i ;
    //循环判断如果is.read()的值不等于-1,则说明字节流中还存在数值,用fos进行输出。
                while((i=is.read())!=-1){
                    fos.write(i);
                     pbt.updateProgress(i);
                }
                notice.setText("下载成功!");
                namelable.setText("");
                urllable.setText("");
            } catch (IOException e) {
    // TODO Auto-generated catch block
                e.printStackTrace();
            }finally{
    //最后流程结束后进行自动fos的关闭。
                try {
                    assert fos != null;
                    fos.close();
                } catch (IOException e) {
    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
    
            }
    
        }
    }
    

    进度条更新线程:

    package tool;
    
    import javax.swing.*;
    import java.util.ArrayList;
    
    public class ProgressBar extends JPanel implements Runnable {
        private final ArrayList<Integer> proList = new ArrayList<Integer>();
        private int progress;//当前进度
        private long totalSize;//总大小
        private boolean run = true;
        private JProgressBar progressBar;
        private JLabel notice;
        public ProgressBar(long totalSize,JProgressBar progressBar,JLabel notice){
            this.totalSize = totalSize;
            this.progressBar=progressBar;
            this.notice=notice;
            //TODO 创建进度条
        }
        /**
         * @param progress 进度
         */
        public void updateProgress(int progress){
            synchronized (this.proList) {
                if(this.run){
                    this.proList.add(progress);
                    this.proList.notify();
                }
            }
        }
    
        public void finish(){
            this.run = false;
            //关闭进度条
        }
    
    
        @Override
        public void run() {
            synchronized (this.proList) {
                try {
                    while (this.run) {
                        if(this.proList.size()==0){
                            this.proList.wait();
                        }
                        synchronized (proList) {
                            this.progress += this.proList.remove(0);
                            int progress=(int) (this.progress/this.totalSize);
                            if (progress<=100){
                                notice.setText(progress+"%");
                            }else {
                                notice.setText("100%");
                            }
                            progressBar.setValue(progress);
                        }
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }
    

    ———————————————2018-7-2更新———————————————————

    刚刚开始用就发现了两个问题,这里记录一下,当碰到下载的文件比较大的时候,int,long无法存放文件的长度,进度条展示会出错。

    还有就是有些文件过大,直接下载内存放不下,必须得用多线程去拆分开来下载。

    https://download.csdn.net/download/hunjue0915/10512412

    没积分的话可以私聊我要代码。

    展开全文
  • 用 Java 编写的URL下载器 workspace
  • 接上一篇我们提到url下载器,那么前期的入库筛选工作已经由url管理器完成了,整理的工作自然要由url下载器接手。当我们需要爬取的数据已经去重后,下载器的主要任务的是这些数据下载下来。所以它的使用也并不复杂,...

    接上一篇我们提到url下载器,那么前期的入库筛选工作已经由url管理器完成了,整理的工作自然要由url下载器接手。当我们需要爬取的数据已经去重后,下载器的主要任务的是这些数据下载下来。所以它的使用也并不复杂,不过需要借助到我们之前所学过的一个库进行操作,相信之前的基础大家都学的很牢固。下面小编就来为大家介绍url下载器及其使用的方法。

    下载器的作用就是接受URL管理器传递给它的一个url,然后把该网页的内容下载下来。python自带有urllib和urllib2等库(这两个库在python3中合并为urllib),它们的作用就是获取指定的网页内容。不过,在这里我们要使用一个更加简洁好用而且功能更加强大的模块:Requests。

    Requests并非python自带模块,需要安装。关于其具体使用方法请查看以往文章,在此不多做介绍。

    下载器接受一个url作为参数,返回值为下载到的网页内容(格式为str)。下面就是一个简单的下载器,其中只有一个简单的函数download():'''

    -----------------------------------------------------------------

    HtmlDownloader

    '''

    class HtmlDownloader(object):

    def download(self, url):

    print "start download"

    if url is None:

    return None

    print "url is None"

    user_agent = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.108 Safari/537.36'

    headers = {'User-Agent':user_agent}

    print "start requests"

    r = requests.get(url, headers=headers)

    #判断响应状态

    if r.status_code == 200:

    r.encoding = 'utf-8'

    print "该页面下载成功!{}".format(url)

    return r.text

    else:

    print "该页面下载失败!{}".format(url)

    return None

    在requests请求中设置User-Agent的目的是伪装成浏览器,这是一只优秀的爬虫应该有的觉悟。

    有些小伙伴已经猜出来了,requests库和我们的爬取数据密不可分,搭配着url下载器我们就可以成功抓取想要的数据了,没学会的小伙伴可以进入我们之前文章回顾一下~更多Python学习指路:PyThon学习网教学中心。

    展开全文
  • 12_URL下载器实现

    2019-06-06 08:40:03
    文章目录网页下载器原理PoolManager获取网页数据添加Headers获取数据下载器代码实现 网页下载器原理 将互联网上URL对应的网页下载到本地的工具 PoolManager获取网页数据 urllib3: Python官方的基础模块,...

    在这里插入图片描述


    博文配套视频课程:24小时实现从零到AI人工智能


    网页下载器原理

    将互联网上URL对应的网页下载到本地的工具,返回的是HTML代码,后续的解析器就是通过解析HTML代码然后获取有价值的数据。这些有价值的数据可以存储到关系数据库、CSV、大数据甚至在内存中直接进行处理
    在这里插入图片描述

    PoolManager获取网页数据

    urllib3爬虫的基础模块,支持自动登录、Cookie等功能。可以通过urlib3与服务器交互并且发送一个请求返回的是请求地址对应的html源码

    from urllib3.poolmanager import PoolManager
    from urllib3 import HTTPResponse
    
    http = PoolManager()
    # 创建一个get/post请求
    res = http.request('get','http://www.163.com')
    # 如果正在返回的状态码为200
    print(res.status)
    # 根据请求的页面设置指定的解析编码,缺省为utf-8
    print(res.data.decode(encoding="gbk"))
    

    添加Headers获取数据

    如果发送请求时配置的是移动客户端的相关参数,返回就是移动端的数据

    from urllib3.poolmanager import PoolManager
    
    http = PoolManager()
    res = http.request('get','http://www.163.com',headers={
        'User-Agent' : 'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N)'
    })
    print(res.status)
    print(res.data.decode())
    

    下载器代码实现

    # 导入urllib3包下面的poolmanager模块,然后加载模块里面PoolManager类
    from urllib3.poolmanager import PoolManager
    from urllib3 import HTTPResponse
    from urllib.parse import urljoin
    
    # 必须传入下载的url地址,返回html源码
    def down_html(url, encoding,method="get"):
        pm = PoolManager()
        res: HTTPResponse = pm.request(method=method, url=url)
        if res.status == 200:
            return res.data.decode(encoding=encoding)
        else:
            return None
    
    if __name__ == "__main__":
        print(down_html(url="http://www.163.com", encoding="gbk"))
    

    在这里插入图片描述

    展开全文
  • 参数输入对话框是特意为新建一个下载时输入各项参数时编写的对话框,在其内部进行URL的输入、下载线程数的输入和下载文件的保存位置的输入或者选择;程序主类的作用主要是搭建主要窗口,以及将参数输入的结果、下载...

    一、 程序总体设计

        程序的主要程序结构由四个类组成,分别是下载线程、统计线程、参数输入对话框和程序主类。下载线程的作用是建立HTTP连接和进行将数据下载到本地文件;统计线程的作用是随时将所有下载线程当前的下载进度输出到程序窗口;参数输入对话框是特意为新建一个下载时输入各项参数时编写的对话框,在其内部进行URL的输入、下载线程数的输入和下载文件的保存位置的输入或者选择;程序主类的作用主要是搭建主要窗口,以及将参数输入的结果、下载进度进行输出,最重要的是控制所有的线程,还有实现对所有控件操作进行响应。这些类的定义如下:

    class ThrDownload extends Thread
    class ThrCount extends Thread
    class MyDialog extends JDialog implements ActionListener
    public class Download
    

           对于所有下载线程的控制方法较为特殊,采用在下载线程中添加下载线程本身的实例数组作为静态数据成员的方式进行统一控制,而下载时的必要参数也都被声明为下载线程的静态数据成员,这样可以在其他类的内部随意通过下载线程类名来访问这些数据成员,以便于统一控制下载线程。

           在程序主窗口中设置了四个按钮,分别是“新建下载”、“继续下载”、“开始”、“暂停”。同时添加一个进度条组件和两个文本编辑框组件进行下载参数或者下载进度的显示,其中进度条专门用来显示下载一个文件总体时的下载进度,用百分比以及进度图形的形式进行显示,第一个文本编辑框会分不同时段显示下载文件的URL或者已经下载的字节数,第个文本编辑框会分不同时段显示下载文件的本地保存位置或者下载速度。程序窗口设计如下:

    •        点击“新建下载”时会打开参数输入对话框,进行所有的参数的输入,输入完成的参数在点击对话框中的确定按钮后会被复制到下载线程的对应参数中。其中保存路径的输入为了方便添加了FileDialog作为输入选择的一种方式,输入完成并且URL合法性检查通过后,将会调用所有下载线程的初始化函数进行初始化,将所有下载线程需要的参数进行赋值,并且尝试进行建立HTTP连接,如果连接失败则在文本框内进行提示,如果成功就初始化输入参数对应的下载线程数量,并且调用其各自的构造函数进行下载线程的初始化,同时为这一次下载初始化一个统计线程。当初始化工作完成后将在两个文本编辑框中进行输出URL和保存路径的提示信息。
    •        点击“继续下载”时,将会弹出一个文件对话框,要求选择需要进行继续下载的配置文件。当选择好配置文件后,将会从选择的文件中读取出所有保存的配置信息,比如URL、下载线程数量、保存路径和各下载线程的已经下载的字节数。之后将用读取出的信息来进行和新建下载中类似的初始化工作,但是此时所有下载线程类的下载开始位置来源是配置文件中读取出的上次结束线程时保存的开始位置,也就是之前已经下载的字节数。
    •        点击“开始”时,将会记录当前开始的时间点,并且启动所有的下载线程进行下载,与此同时启动统计线程,随时将下载进度输出到窗口。在统计线程的线程体中,除了随时输出当前下载的进度外,还需要判断当前是否所有线程都已经自动结束,如果是,那么就需要首先判断当前是否是继续下载,是的话就将配置文件删除。
    •        “暂停”按钮被按下时,检查所有的下载线程,如果还有线程处于活动状态,那么就新建配置文件,将当前各下载线程的下载进度保存到配置文件中,方便下次继续下载,同时将所有的下载线程结束。此时,可以点击窗口关闭按钮结束程序,在下次重新打开程序后,或者直接新建下载,所有参数都和上次一样时,点击开始下载就可以进行继续下载。

     

    二、主要数据结构描述

    • 下载线程ThrDownload:

        下载线程本身是一个进行HTTP文件下载的线程,对应的私有数据成员是URL名、输入输出流、下载文件的开始位置start和结束位置end、读写缓冲区和已经下载的字节数等用于统计的参数(已下载字节数分为此次开始下载后的总长度len和对于整个文件来说的已下载长度finish),其线程体的操作是将URL对应文件的start到end位置的数据下载到本地文件对应位置,并且实时更新统计参数。此外,为了方便统一控制所有的下载线程,将下载线程的实例定义在线程类内部,声明为静态参数,所以可以直接通过类名来访问。和下载线程实例一样被定义为静态数据成员的还有需要下载文件的总长度、下载线程数、下载文件的URL、保存文件的路径名、统计线程、当前需要下载的文件是否是继续下载isPart、各下载线程下载的开始位置,这些静态数据成员的作用也是为了方便统一控制所有下载线程。下载线程的构造函数中会从静态参数中读取自己需要的参数,如下载文件的开始位置和结束位置,并且建立其文件读写的接口和HTTPURL连接。所有下载线程的初始化如总体设计中所述,会进行所有下载参数的赋值,并且自动确定所以下载线程的下载开始和结束位置。此外,为了方便在其他类中获取已下载的数据长度,定义了两个分别返回len和finish的参数。

           下载线程中所有的数据成员如下:

        private int no; // 线程号
        private RandomAccessFile out;
        private InputStream in; // 输入字节流
        private URL url; // URL
        private final int start; // 该下载线程下载的文件起始和结束位置
        private int end;
        private byte[] b; // 读写缓冲区
        private int len; // 该下载线程开始下载到现在下载的字节数
        private int finish; // 该下载线程总下载字节数
    
        // 下载线程共享资源
        public static int file_len = 0; // 需要下载的文件总长度
        public static int buf_len = 8192; // 缓冲区大小:1MB
        public static int num_thread = 1; // 下载线程数
        public static String url_name; // 下载文件的url名
        public static String save_name; // 保存文件名
        public static ThrDownload[] thr_download; // 下载线程
        public static ThrCount thr_count; // 统计线程
        public static boolean isPart = false; // 当前需下载的文件是否已经下载过一部分,默认为否
        public static int[] start_pos; // 从临时文件读取的各下载线程开始位置
    
    • 程序主要类Download

           程序主要类中的数据成员主要是主窗口的各个组件,而主要进行的操作就是所有组件的初始化以及添加到主窗口并显示窗口,最重要的是为了所有按钮添加事件监听程序,不同的按钮对应不同的操作,“新建下载”是输入所有参数和初始化下载线程(可能读取配置文件),“继续下载”是打开一个存在的配置文件并且用其中的信息进行下载线程的初始化,“开始”是启动所有下载线程和统计线程,“暂停”是保存当前下载进度到配置文件并且结束所有下载线程。

       

    三、主要算法描述

    • 下载线程的线程体:

           用一个整型数据int  L记录从URL文件读取一次数据所读出的字节数,循环读取数据到缓冲区,并将缓冲区中数据保存到本地文件中,同时用L更新该线程已下载数据的进度。如果判断到读取出的字节数为-1,说明该下载线程已经下载完成了需要下载的数据,那么关闭输入输出流。

    • 下载速度和下载进度的计算:

           因为在下载线程中有此次开始下载后已下载的数据长度len和该下载文件总的已下载数据长度finish,并且可以用查询函数获得其值,所以在每次开始下载时记录当前的时间点,然后在之后每隔一段时间获取新的时间点计算出时间间隔,再用所有线程的len之和除以该时间间隔就可以得出下载速度。而下载进度就是将所有线程的finish之和除以下载文件的总大小即可得到。

    • 下载线程的下载开始位置确定

           在下载线程中添加一个标识本次下载是否是继续下载的布尔变量,以及一个用以保存所有下载线程的下载开始位置的数组,该数组只有在当前是继续下载时才会使用。如果当前是第一次下载,那么所有下载线程的开始位置默认都是从头开始,但如果是继续下载那么其开始位置就是从配置中读取出的开始位置,从配置文件中读取出的开始位置首先爆出到先前提到的数组中,然后在下载线程进行初始化时再赋值给每个线程。

    • 配置文件的输入输出:

           当点击了暂停按钮。并且当前仍有下载线程处于运行状态,那么就将当前下载的信息进行保存到配置文件。如果点击了继续下载就打开一个配置文件进行读取下载信息。此外,在统计线程检查到当前已经完成了文件下载时就将对应的存在的配置文件进行删除。

           在保存时,将当前下载的URL、下载线程数量、保存路径和每个下载线程当前已经下载的总数据长度finish保存到配置文件中。URL保存的表项是“URL”,保存路径的表项是“Dir”,下载线程的数量保存表项是“Thr”,而各下载线程的开始位置统一保存在一个名为“Prog”的表项下,每个长度之间用“@”来进行分隔。同样的,在读取时,也是将所有信息按保存时的顺序读取出来,注意读取开始位置是每隔一个“@”读取一个数据,再分别赋值给每个下载线程的已下载总长度finish,并且将其作为开始位置。

     

    四、程序测试

    进入程序时主界面:

    点击新建下载弹出参数输入对话框:

    点击保存文件路径旁边的按钮进行文件位置选择:

    点击确定后回到主界面:

    点击开始后下载进度显示:

    点击暂停后界面,以及出现的配置文件:

    点击继续下载,选择出现的配置文件,点击开始继续下载:

    直到完成下载,并查看下载完成的文件(配置文件已删除):

    五、源程序附录

    import java.io.*;
    import java.awt.*;
    import java.awt.event.*;
    import javax.swing.*;
    import java.net.*;
    import java.text.DecimalFormat;
    import java.util.*;
    import java.util.concurrent.TimeUnit;
    
    //下载线程
    class ThrDownload extends Thread {
        private int no; // 线程号
        private RandomAccessFile out;
        private InputStream in; // 输入字节流
        private URL url; // URL
        private final int start; // 该下载线程下载的文件起始和结束位置
        private int end;
        private byte[] b; // 读写缓冲区
        private int len; // 该下载线程开始下载到现在下载的字节数
        private int finish; // 该下载线程总下载字节数
    
        // 下载线程共享资源
        public static int file_len = 0; // 需要下载的文件总长度
        public static int buf_len = 8192; // 缓冲区大小:1MB
        public static int num_thread = 1; // 下载线程数
        public static String url_name; // 下载文件的url名
        public static String save_name; // 保存文件名
        public static ThrDownload[] thr_download; // 下载线程
        public static ThrCount thr_count; // 统计线程
        public static boolean isPart = false; // 当前需下载的文件是否已经下载过一部分,默认为否
        public static int[] start_pos; // 从临时文件读取的各下载线程开始位置
    
        // 构造函数
        public ThrDownload(final int no) {
            final int block_len = file_len / num_thread; // 计算每个下载线程需要下载的数据长度
            if (!isPart) // 第一次下载
                start = block_len * (no - 1); // 该线程下载的数据开始位置
            else { // 不是第一次下载
                start = block_len * (no - 1) + start_pos[no - 1];
            }
            end = (block_len * no) - 1; // 该线程下载的数据结束位置
            if (no == num_thread)
                end = file_len - 1;
            len = 0; // 当前已下载的字节数初始化
            finish = start - block_len * (no - 1); // 当前总共下载的字节数
            try {
                url = new URL(url_name);
                final HttpURLConnection con = (HttpURLConnection) url.openConnection();
                con.setRequestProperty("Range", "byte=" + start + "-" + end);
                in = con.getInputStream();
                if (con.getResponseCode() >= 300)
                    new Exception("Http响应问题:" + con.getResponseCode());
                out = new RandomAccessFile(save_name, "rw");
                this.no = no;
                out.seek(start); // 在保存文件中确定保存的位置
                b = new byte[buf_len]; // 初始化缓冲区
            } catch (final Exception e) {
                System.out.println(e.toString());
            }
        }
    
        // 所有下载线程的初始化函数
        public static boolean init(final String url_name, final String save_name, final int num_thread) {
            ThrDownload.url_name = url_name;
            ThrDownload.save_name = save_name;
            ThrDownload.num_thread = num_thread;
            try {
                final URL url = new URL(url_name);
                final HttpURLConnection con = (HttpURLConnection) url.openConnection();
                ThrDownload.file_len = con.getContentLength();
            } catch (final Exception e) {
                return false;
            }
            if (file_len == -1)
                return false; // 为-1说明资源分块传输无Conten_length
    
            thr_download = new ThrDownload[num_thread];
            for (int i = 0; i < num_thread; i++) {
                thr_download[i] = new ThrDownload(i + 1); // 下载线程的初始化
            }
            thr_count = new ThrCount(); // 统计线程的初始化
            return true;
        }
    
        // 下载线程体
        public void run() {
            int L; // 读取出的字节数,为-1的话已经读取到文件末尾
            try {
                while (true) {
                    L = in.read(b); // 读取直接到缓冲区
                    if (L == -1)
                        break;
                    out.write(b, 0, L); // 将缓冲区写到保存文件
                    len += L;
                    finish += L;
                }
                in.close();
                out.close();
            } catch (final Exception e) {
            }
        }
    
        // 查询开始下载到现在当前已经下载的数据长度
        public int getLen() {
            return len;
        }
    
        // 查询当前已经保存保存的数据长度
        public int getFinish() {
            return finish;
        }
    }
    
    // 统计线程
    class ThrCount extends Thread {
        public static double begin_time; // 下载开始时间
        public static double current_time; // 当前时间
    
        public void run() {
            while (true) {
                try {
                    TimeUnit.SECONDS.sleep(1);// 每隔一秒输出一次进度
                } catch (final InterruptedException ex) {
                }
                current_time = (new Date()).getTime() / 1000.0;
                double percent = 0;
                double speed = 0; // 计算下载百分比和平均下载速度
                for (int i = 0; i < ThrDownload.num_thread; i++) {
                    percent += ThrDownload.thr_download[i].getFinish();
                    speed += ThrDownload.thr_download[i].getLen();
                }
    
                // 输出当前进度等
                DecimalFormat[] df = new DecimalFormat[4]; // 将double格式化
                for (int i = 0; i < 4; i++)
                    df[i] = new DecimalFormat("###.0");
                Download.tf1.setText("已下载文件大小:" + df[0].format(percent / 1000) + "KB / "
                        + df[1].format(ThrDownload.file_len / 1000) + "KB");
                speed = speed / 1000.0 / (current_time - begin_time); // 单位KB/S
                percent /= ThrDownload.file_len;
                Download.tf2.setText(df[2].format(percent * 100) + "%已下载, 平均下载速度=" + df[3].format(speed) + "KB/S");
                Download.pb.setValue((int) (percent * 100)); // 更新进度条的进度
                Download.pb.repaint(); // 手动重新绘制进度条
    
                // 判断是否所有下载线程都已经结束,若否则继续下载
                int i;
                for (i = 0; i < ThrDownload.num_thread; i++)
                    if (ThrDownload.thr_download[i].isAlive())
                        break;
                if (i >= ThrDownload.num_thread) // 全部线程下载完成
                {
                    for (i = 0; i < ThrDownload.num_thread; i++)
                        ThrDownload.thr_download[i].stop();
                    try {
                        File destroy = new File(ThrDownload.save_name + ".cfg");
                        if (destroy.exists()) // 存在配置文件
                            destroy.delete();
                    } catch (Exception e) {
                        System.out.println(e.toString());
                    }
                    break;
                }
            }
        }
    }
    
    // 输入参数对话框
    class MyDialog extends JDialog implements ActionListener {
        JTextField input_url, input_num, input_pathname;
        JButton button_down, button_choose; // 确定按钮
        FileDialog save; // 选择保存文件的位置
        String url = "", pathname = "";
        int num; // 下载线程数
    
        MyDialog(final JFrame f, final String s) { // 传入父容器和对话框标题
            super(f, s);
            setLayout(new FlowLayout(FlowLayout.LEFT, 50, 20));
            setBounds(600, 260, 500, 400); // 设置对话框位置和大小
            setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
            // 添加输入url的组件
            final JLabel label1 = new JLabel("输入URL:");
            label1.setFont(new Font("宋体", Font.BOLD, 15));
            add(label1);
            input_url = new JTextField(35);
            input_url.setFont(new Font("宋体", Font.BOLD, 20));
            input_url.setText("https://qd.myapp.com/myapp/qqteam/pcqq/PCQQ2019.exe");
            add(input_url);
    
            // 添加输入下载线程数的组件
            final JLabel label2 = new JLabel("输入下载线程数:");
            label2.setFont(new Font("宋体", Font.BOLD, 15));
            add(label2);
            input_num = new JTextField(35);
            input_num.setFont(new Font("宋体", Font.BOLD, 20));
            input_num.setText("5");
            add(input_num);
    
            // 添加输入保存文件路径名的组件
            final JLabel label3 = new JLabel("输入保存文件路径名:");
            label3.setFont(new Font("宋体", Font.BOLD, 15));
            add(label3);
            input_pathname = new JTextField(30);
            input_pathname.setFont(new Font("宋体", Font.BOLD, 20));
            input_pathname.setText("");
            add(input_pathname);
            // 文件对话框初始化
            save = new FileDialog(this, "选择保存位置", FileDialog.SAVE);
            button_choose = new JButton("...");
            button_choose.addActionListener(this);
            button_choose.setPreferredSize(new Dimension(20, 30));
            add(button_choose);
    
            // 添加确定按钮
            button_down = new JButton("确定");
            button_down.addActionListener(this);
            button_down.setFont(new Font("宋体", Font.BOLD, 20));
            button_down.setPreferredSize(new Dimension(100, 50));
            add(button_down);
        }
    
        public void actionPerformed(final ActionEvent e) {
            switch (e.getActionCommand()) {
            case "...":
                save.setVisible(true);
                input_pathname.setText(save.getDirectory() + save.getFile());
                break;
            case "确定":
                try {
                    url = input_url.getText();
                    URL test = new URL(url);
                } catch (MalformedURLException ex) { // 检查URL合法性
                    JOptionPane.showMessageDialog(this, "URL格式错误!", "错误", JOptionPane.ERROR_MESSAGE);
                    url = "";
                    return;
                }
                pathname = input_pathname.getText();
                num = Integer.parseInt(input_num.getText());
                setVisible(false);
                break;
            default:
                break;
            }
    
        }
    
        public String get_url() {
            return url;
        }
    
        public int get_num() {
            return num;
        }
    
        public String get_pathname() {
            return pathname;
        }
    }
    
    public class Download {
        private static JFrame f;
        public static JProgressBar pb; // 进度条
        public static JTextField tf1, tf2; // 编辑框组件
        private JButton[] bt; // 按钮组件
        FileDialog con_download; // 继续下载时打开配置文件的对话框
        private MyDialog dialog;
    
        class event_window extends WindowAdapter { // 窗口关闭事件监听
            public void windowClosing(final WindowEvent e) {
                System.exit(0);
            }
        }
    
        class event_action implements ActionListener { // 按钮点击事件监听
            public void actionPerformed(final ActionEvent e) {
                final String s = e.getActionCommand();
                switch (s) {
                case "新建下载":
                    dialog.setVisible(true);
                    ThrDownload.isPart = false;
                    if (!ThrDownload.init(dialog.get_url(), dialog.get_pathname(), dialog.get_num()))
                        tf1.setText("下载线程初始化失败!");
                    if (dialog.get_url() != "")
                        tf1.setText("URL:" + dialog.get_url());
                    if (dialog.get_pathname() != "")
                        tf2.setText("下载文件保存到" + dialog.get_pathname());
                    break;
                case "继续下载":
                    con_download.setVisible(true);
                    // 读取配置文件
                    String url="",save_name="";
                    int n=0;
                    try {
                        ThrDownload.isPart = true;
                        FileReader propFile = new FileReader(con_download.getDirectory()+con_download.getFile());
                        Properties prop = new Properties();
                        prop.load(propFile);
                        url = prop.getProperty("URL"); // 载入URL
                        save_name = prop.getProperty("Dir"); // 载入路径
                        n = Integer.parseInt(prop.getProperty("Thr")); // 载入线程数
                        ThrDownload.start_pos = new int[n];
                        String progress = prop.getProperty("Prog"); // 解析每个线程的进度
                        String[] strProg = progress.split("@");
                        if (strProg.length != n)
                            throw new Exception("Error.");
                        for (int i = 0; i < n; i++) 
                            ThrDownload.start_pos[i] = Integer.parseInt(strProg[i]);
                    } catch (Exception ex) {
                        ex.printStackTrace();
                    }
                    if (!ThrDownload.init(url, save_name, n))
                        tf1.setText("下载线程初始化失败!");
                    if (url != "")
                        tf1.setText("URL:" + url);
                    tf2.setText("继续下载:" + save_name);
                    break;
                case "开始":
                    ThrCount.begin_time = (new Date()).getTime() / 1000.0;
                    for (int i = 0; i < ThrDownload.num_thread; i++)
                        ThrDownload.thr_download[i].start(); // 所有线程开始下载
                    ThrDownload.thr_count.start(); // 开始统计
                    break;
                case "暂停": {
                    tf2.setText("已暂停下载...");
                    int i;
                    for (i = 0; i < ThrDownload.num_thread; i++)
                        if (ThrDownload.thr_download[i].isAlive())
                            break;
                    if (i != ThrDownload.num_thread) { // 退出时还有线程没有下载完成,保存配置文件
                        try {
                            Properties prop = new Properties();
                            prop.setProperty("URL", ThrDownload.url_name);
                            prop.setProperty("Dir", ThrDownload.save_name);
                            prop.setProperty("Thr", Integer.toString(ThrDownload.num_thread));
                            String temp = Integer.toString(ThrDownload.thr_download[0].getLen());
                            for (int j = 1; j < ThrDownload.num_thread; j++) {
                                temp = temp + "@" + Integer.toString(ThrDownload.thr_download[j].getFinish());
                            }
                            prop.setProperty("Prog", temp);
                            File propFile = new File(ThrDownload.save_name + ".cfg");
                            prop.store(new FileWriter(propFile), "");
                        } catch (Exception ex) {
                            ex.printStackTrace();
                        }
                    }
                    for (i = 0; i < ThrDownload.num_thread; i++)
                        ThrDownload.thr_download[i].stop();
                }
                    ThrDownload.thr_count.stop();
                    break;
                default:
                    break;
                }
            }
        }
    
        public void init() { // 图形界面初始化
            // 容器和布局定义
            f = new JFrame("多线程下载器");
            f.setLayout(null);
    
            // 进度条初始化
            pb = new JProgressBar(0, 100);
            // 设置进度最小最大值
            pb.setValue(0); // 当前值
            pb.setStringPainted(true);// 绘制百分比文本(进度条中间显示的百分数)
            pb.setIndeterminate(false);
            pb.setPreferredSize(new Dimension(510, 20));
            f.add(pb);
            pb.setBounds(50, 10, 500, 30);
    
            // 对话框初始化
            dialog = new MyDialog(f, "输入下载参数");
            dialog.setModal(true);
    
            //文件对话框的初始化
            con_download = new FileDialog(f,"选择继续下载的配置文件",FileDialog.LOAD);
    
            // 显示框初始化
            tf1 = new JTextField(56);
            tf1.setFont(new Font("宋体", Font.BOLD, 15));
            tf1.setText("URL");
            f.add(tf1);
            tf1.setBounds(50, 50, 500, 30);
            tf2 = new JTextField(56);
            tf2.setFont(new Font("宋体", Font.BOLD, 15));
            tf2.setText("保存路径");
            f.add(tf2);
            tf2.setBounds(50, 90, 500, 30);
    
            // 按钮初始化
            bt = new JButton[4];
            bt[0] = new JButton("新建下载");
            bt[1] = new JButton("继续下载");
            bt[2] = new JButton("开始");
            bt[3] = new JButton("暂停");
            for (int i = 0; i < 4; i++) // 设置按钮字体样式
                bt[i].setFont(new Font("宋体", Font.BOLD, 17));
            for (int i = 0; i < 4; i++)
                f.add(bt[i]);
            bt[0].setBounds(50, 130, 110, 30);
            bt[1].setBounds(180, 130, 110, 30);
            bt[2].setBounds(310, 130, 110, 30);
            bt[3].setBounds(430, 130, 110, 30);
    
            // 添加事件监听
            final event_window e_w = new event_window();
            final event_action e_c = new event_action();
            f.addWindowListener(e_w);
            for (int i = 0; i < 4; i++) {
                bt[i].addActionListener(e_c);
            }
        }
    
        public void display() { // 显示窗口
            f.setSize(600, 230);
            f.setLocation(700, 350);
            f.setVisible(true);
            f.setResizable(false);
        }
    
        public static void main(final String args[]) {
            final Download a = new Download();
            a.init();
            a.display();
        }
    }
    

     

    展开全文
  • 爬虫初探系列一共4篇,耐心看完,我相信你就能基本了解爬虫是怎样工作的了,目录如下:代码已上传至github,在python2.7下测试成功(请原谅我浓浓的乡村非主流代码风格)summerliehu/...URL下载器应该包含两个...
  • URL文件批量下载器.zip

    2021-02-26 00:07:04
    URL文件批量下载工具,使用说明查看readme
  • 当我们需要有一批货物需要存放时,最好的方法就是有一个仓库进行保管。我们可以把URL管理器看成一个收集了数据的大仓库,而下载器就是这个仓库货物的搬运者。关于下载器的问题,我们暂且不谈。... URL下载器应该能识别
  • Python爬虫之URL管理器:Python爬虫:URL管理器实现方式:Python爬虫之网页下载器:urllib2实现网页下载器的三种方法:具体代码:Python网页解析器:例子:import requestsfrom bs4 import BeautifulSoupdef ...
  • 基于Android的YouTube网址提取 这些是YouTube视频或音频文件的网址,因此您可以流式传输或下载它们。 它具有年龄验证规避和签名解密方法(主要用于vevo视频)的功能。 构建: 依赖关系: Gradle 始终从具有所有...
  • Python爬虫之URL管理器:Python爬虫:URL管理器实现方式:Python爬虫之网页下载器:urllib2实现网页下载器的三种方法:具体代码: Python网页解析器:...
  • Python爬虫通过URL管理器,判断是否有待爬URL,如果有待爬URL,通过调度器进行传递给下载器,下载URL内容,并通过调度器传送给解析器,解析URL内容,并将价值数据和新URL列表通过调度器传递给应用程序,并输出价值...
  • 里面详细分析了爬虫的步骤,对每一步代码都有详细的注释说明,可通过本案例掌握python爬虫的特点:1、爬虫调度入口(crawler_main.py)# coding:utf-8from com.wenhy.crawler_baidu_baike import url_manager...
  • url管理

    2017-07-11 15:58:34
    URL管理器的实现方式分三种 1.python内存。(待爬取url的集合 已爬取url的集合) 2.关系数据库. urls(url ,is_crawled)  ...网页下载器 1. urllib2 (三种方式) import urllib2 #直接请求 response=urll
  • jqURL-URL下载器和JSON解析器 想象一下命令行外壳程序(例如BaSH)调用cURL然后将输出到jq管道进行多少次。 更糟糕的是,同一休息端点在一个脚本中或脚本之间被多次使用。 输入jqurl ,这个紧凑的工具以一个二进制...
  • 当我们需要有一批货物需要存放时,最好的方法就是有一个仓库进行保管。我们可以把URL管理器看成一个收集了数据的大仓库,而下载器就是这个仓库货物的搬运者。关于下载器的问题,我们...URL下载器应该包含两个仓库...
  • 涡轮计算机 线性URL文件下载器,使用URLMON库提供完整的URL和DIR自定义 学分 Hoven-较小的代码段的一个不错的基础。 (无链接!) 执照 结束语 用 :heart_with_ribbon: 通过传统主义
  • 线性URL文件下载器,使用URLMON库提供完整的URL和DIR自定义 回购名称是怎么回事? 与github默认存储库名称等的一个小模因... 学分 Hoven-较小的代码段的一个不错的基础。 StackOverflow-... OBV! 安迪-一些下载...
  • 使用java实现一个可视化的音乐下载器,主要采用的技术是java的URL类和Swing可视化包,界面比较简洁,可以下载网络上的大部分歌曲
  • 当我们需要有一批货物需要存放时,最好的方法就是有一个仓库进行保管。我们可以把URL管理器看成一个收集了数据的大仓库,而下载器就是这个仓库货物的搬运者。关于下载器的问题,我们...URL下载器应该包含两个仓库...
  • 总体内容在学习下面的知识前请在 mac电脑搭建一下 Apache 服务器1、NSURLConncetion 下载2、NSURLSession下载大文件3、下载管理(多文件下载)一、NSURLConncetion 下载1.1、我们先使用NSURLConncetion 下载一个视频...
  • 当我们需要有一批货物需要存放时,最好的方法就是有一个仓库进行保管。我们可以把URL管理器看成一个收集了数据的大仓库,而下载器就是这个仓库货物的搬运者。关于下载器的问题,我们...URL下载器应该包含两个仓库...
  • java实现下载器(以及创建一个URL对象) 1.思路讲解: (1)注意路径:是网络路径噢 (2)创建创建网路协议对象(远程对象):HttpURLConnection urlConnection (3)定位网络资源:URL url (4)调用url的open...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 4,253
精华内容 1,701
关键字:

url下载器