java - 进度条和下载 [英] java - progress bar and download

查看:89
本文介绍了java - 进度条和下载的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

下面的代码完全符合我所期望的一件事.我只需要让这个下载更多不同的 URL(图片) 遗憾的是我不知道该怎么做.如果有人能帮我解决这个问题,我将不胜感激.

import java.io.BufferedOutputStream;导入 java.io.FileNotFoundException;导入 java.io.IOException;导入 java.net.HttpURLConnection;导入 java.net.URL;导入 javax.swing.JFrame;导入 javax.swing.JProgressBar;导入 javax.swing.SwingUtilities;导入 javax.swing.WindowConstants;公共类进度条{公共静态无效主(字符串 [] args){final JProgressBar jProgressBar = new JProgressBar();jProgressBar.setMaximum(100000);JFrame frame = new JFrame();frame.setContentPane(jProgressBar);frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);frame.setSize(300, 70);frame.setVisible(true);可运行更新线程 = 新可运行(){公共无效运行(){尝试 {URL url = new URL("http://www.drgarbage.com/img/howto/cfgf-tutorial/createcfg.png");HttpURLConnection httpConnection = (HttpURLConnection) (url.openConnection());long completeFileSize = httpConnection.getContentLength();java.io.BufferedInputStream in = new java.io.BufferedInputStream(httpConnection.getInputStream());java.io.FileOutputStream fos = new java.io.FileOutputStream("picture.png");java.io.BufferedOutputStream 回合 = 新的 BufferedOutputStream(fos, 1024);字节[]数据=新字节[1024];长下载文件大小 = 0;整数 x = 0;while ((x = in.read(data, 0, 1024)) >= 0) {下载文件大小 += x;//计算进度final int currentProgress = (int) (((((double)downloadedFileSize)/((double)completeFileSize)) * 100000d);//更新进度条SwingUtilities.invokeLater(new Runnable() {@覆盖公共无效运行(){ProgressBar.setValue(currentProgress);}});回合.写(数据,0,x);}回合.close();附寄();} catch (FileNotFoundException e) {} catch (IOException e) {}}};新线程(更新线程).开始();}}

解决方案

这里有一个基于 https://docs.oracle.com/javase/tutorial/uiswing/examples/components/ProgressBarDemoProject/src/components/ProgressBarDemo.java>

进度计算使用了一些作弊,因为它假设所有文件的大小大致相同.预取所有文件大小,然后对适当的总数进行计算会更合适.

我添加了一个额外的进度条,根据中给出的解决方案指示当前文件下载https://stackoverflow.com/a/8917565/3469592.我不确定这是否是好的做法.欢迎提出批评和改进建议.

警告:代码被人为减慢以使其更易于观看.如果您真的想使用它,请删除 Thread.sleep(200) 部分!

/** 版权所有 (c) 1995、2008,Oracle 和/或其附属公司.版权所有.**以源代码和二进制形式重新分发和使用,有或没有* 允许修改,前提是以下条件* 满足:** - 源代码的重新分发必须保留上述版权* 注意,此条件列表和以下免责声明.** - 以二进制形式重新分发必须复制上述版权* 注意,此条件列表和以下免责声明在* 随分发提供的文档和/或其他材料.** - 既不是 Oracle 的名称,也不是其名称* 贡献者可用于认可或推广衍生产品* 未经本软件事先书面许可.** 本软件由版权所有者和贡献者作为* 是"以及任何明示或暗示的保证,包括但不限于,* 对特定商品的适销性和适用性的默示保证* 目的不明确.在任何情况下,版权所有者或* 贡献者对任何直接的、间接的、偶然的、特殊的、* 示范性或后果性损害(包括但不限于,* 替代品或服务的采购;丢失使用、数据或* 利润;或业务中断)无论是由什么原因引起的,并且基于任何理论* 责任,无论是合同责任、严格责任还是侵权责任(包括* 疏忽或以其他方式)因使用本产品而以任何方式产生* 软件,即使被告知存在此类损坏的可能性.*/导入 java.io.FileNotFoundException;导入 java.io.IOException;导入 java.awt.*;导入 java.awt.event.*;导入 javax.swing.*;导入 java.beans.*;公共类 ProgressBarDemo 扩展了 JPanel实现 ActionListener,属性更改监听器 {私人 JProgressBar 整体进度条;私人 JProgressBar currentProgressBar;私人 JButton 开始按钮;私有 JTextArea 任务输出;私人任务;类任务扩展了 SwingWorker{私人最终 JProgressBar currentProgressBar;私人任务(JProgressBar progressBar){当前进度条 = 进度条;}私有无效下载(字符串 urlString,int 文件编号,int 总数){java.io.InputStream in = null;java.io.OutputStream out = null;尝试 {taskOutput.append("下载文件" + fileNumber + "...");java.net.URL url = new java.net.URL(urlString);java.net.HttpURLConnection httpConnection = (java.net.HttpURLConnection) (url.openConnection());long completeFileSize = httpConnection.getContentLength();in = httpConnection.getInputStream();out = new java.io.FileOutputStream("图片"+fileNumber+".p​​ng");最终字节[]数据=新字节[1024];长下载文件大小 = 0;整数计数;while ((count = in.read(data, 0, 1024)) != -1) {//--------------------------//TODO:使下载速度变慢,以便您可以更好地观看内容,请勿在生产代码中使用!尝试 {线程睡眠(200);} catch (InterruptedException 忽略) {}//--------------------------下载文件大小 += 计数;/* 计算进度(便宜的变体,我们假设文件大小大致相同),另一种更合适的方法是预取所有文件大小并给出实际进度 */final int currentProgress = (int) (((double)downloadedFileSize)/((double)completeFileSize) * 100d );final int scaledCurrentProgress = currentProgress/total;final int totalProgress = (int) (((double)fileNumber/(double)total) * 100d);/* 进度通知 */setProgress(Math.min(scaledCurrentProgress + totalProgress,100));发布(Math.min(currentProgress,100));/* 保存下载的数据 */out.write(data, 0, count);}taskOutput.append("完成!\n");} catch (FileNotFoundException e) {taskOutput.append("文件未找到:" + e);} catch (IOException e) {taskOutput.append("IO 异常:" + e);} 捕获(异常 e){taskOutput.append("出了点问题:" + e);} 最后 {尝试 {如果(在!= null){附寄();}如果(出!= null){关闭();}} catch (IOException e) {taskOutput.append("IO 异常:" + e);}}}/** 主要任务.在后台线程中执行.*/@覆盖公共无效 doInBackground() {//TODO: 这个数据可能会在构造函数中提供给类java.util.ListurlStrings = java.util.Arrays.asList("http://imgs.xkcd.com/comics/tamagotchi_hive.png","http://imgs.xkcd.com/comics/solar_system_questions.png","http://imgs.xkcd.com/comics/90s_kid.png","http://imgs.xkcd.com/comics/xkcd_phone_3.png","http://imgs.xkcd.com/comics/episode_vii.png");设置进度(0);int numberOfURLs = urlStrings.size();for (int i = 0; i  progressList) {final int progress = progressList.get(progressList.size() - 1);currentProgressBar.setValue(progress);}/** 在事件调度线程中执行*/@覆盖公共无效完成(){设置光标(空);//关闭等待光标taskOutput.append("所有文件已下载!\n");}}//类任务结束公共 ProgressBarDemo() {超级(新的边框布局());//创建演示的用户界面.startButton = new JButton("开始");startButton.setActionCommand("开始");startButton.addActionListener(this);totalProgressBar = new JProgressBar(0, 100);totalProgressBar.setValue(0);totalProgressBar.setStringPainted(true);currentProgressBar = new JProgressBar(0, 100);currentProgressBar.setValue(0);currentProgressBar.setStringPainted(true);taskOutput = new JTextArea(5, 20);taskOutput.setMargin(new Insets(5,5,5,5));taskOutput.setEditable(false);JPanel 面板 = new JPanel();panel.setLayout(new GridLayout(3,2));panel.add(new JLabel("当前文件"));panel.add(currentProgressBar);panel.add(new JLabel("总体进度"));panel.add(overallProgressBar);panel.add(startButton);添加(面板,BorderLayout.PAGE_START);添加(新 JScrollPane(任务输出),BorderLayout.CENTER);setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));}/*** 当用户按下开始按钮时调用.*/公共无效动作执行(ActionEvent evt){startButton.setEnabled(false);setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));//javax.swing.SwingWorker 的实例不可重用,所以//我们根据需要创建新实例.任务 = 新任务(currentProgressBar);task.addPropertyChangeListener(this);任务.执行();}/*** 当任务的进度属性改变时调用.*/公共无效propertyChange(PropertyChangeEvent evt){if ("progress" == evt.getPropertyName()) {int progress = (Integer) evt.getNewValue();totalProgressBar.setValue(progress);}}/*** 创建 GUI 并显示它.与所有 GUI 代码一样,这必须运行* 在事件调度线程上.*/私有静态无效 createAndShowGUI() {//创建并设置窗口.JFrame frame = new JFrame("ProgressBarDemo");frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//创建并设置内容窗格.JComponent newContentPane = new ProgressBarDemo();newContentPane.setOpaque(true);//内容窗格必须是不透明的frame.setContentPane(newContentPane);//显示窗口.框架.pack();frame.setVisible(true);}公共静态无效主(字符串 [] args){//为事件调度线程安排一个作业://创建并显示此应用程序的 GUI.javax.swing.SwingUtilities.invokeLater(new Runnable() {公共无效运行(){createAndShowGUI();}});}}

The code below does exactly what I need expect one thing. I just need to make this download a few more different URLs (pictures) sadly I got no idea how to do it. If anyone could help me to solve this I would be so thankful.

import java.io.BufferedOutputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;

import javax.swing.JFrame;
import javax.swing.JProgressBar;
import javax.swing.SwingUtilities;
import javax.swing.WindowConstants;

public class Progressbar {

  public static void main(String[] args) {

    final JProgressBar jProgressBar = new JProgressBar();
    jProgressBar.setMaximum(100000);
    JFrame frame = new JFrame();
    frame.setContentPane(jProgressBar);
    frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    frame.setSize(300, 70);
    frame.setVisible(true);
    Runnable updatethread = new Runnable() {
      public void run() {
        try {
          URL url = new URL("http://www.drgarbage.com/img/howto/cfgf-tutorial/createcfg.png");
          HttpURLConnection httpConnection = (HttpURLConnection) (url.openConnection());                        
          long completeFileSize = httpConnection.getContentLength();
          java.io.BufferedInputStream in = new     java.io.BufferedInputStream(httpConnection.getInputStream());
          java.io.FileOutputStream fos = new java.io.FileOutputStream("picture.png");
          java.io.BufferedOutputStream bout = new BufferedOutputStream(fos, 1024);                       
          byte[] data = new byte[1024];
          long downloadedFileSize = 0;
          int x = 0;
          while ((x = in.read(data, 0, 1024)) >= 0) { 
            downloadedFileSize += x;

            // calculate progress
            final int currentProgress = (int) ((((double)downloadedFileSize) / ((double)completeFileSize)) * 100000d);

            // update progress bar
            SwingUtilities.invokeLater(new Runnable() {

              @Override
              public void run() {
                ProgressBar.setValue(currentProgress);
              }
            });
            bout.write(data, 0, x);
          }
          bout.close();
          in.close();
        } catch (FileNotFoundException e) {
        } catch (IOException e) {
        }
      }
    };
    new Thread(updatethread).

    start();
  }
}

解决方案

Here's a quick solution based on https://docs.oracle.com/javase/tutorial/uiswing/examples/components/ProgressBarDemoProject/src/components/ProgressBarDemo.java

The progress calculation uses a bit of cheating in that it assumes that all files are roughly the same size. It would be more proper to prefetch all file sizes and then do calculations on the proper total.

Edit: I've added an additional progress bar indicating current file download based on the solution given in https://stackoverflow.com/a/8917565/3469592. I'm not sure, whether this is good practice. Criticism and suggestions for improvement are welcome.

Warning: The code is artificially slowed down to make it easier to watch. Remove the Thread.sleep(200) part if you actually want to use this!

/*
 * Copyright (c) 1995, 2008, Oracle and/or its affiliates. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Oracle or the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */ 

import java.io.FileNotFoundException;
import java.io.IOException;


import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.beans.*;

public class ProgressBarDemo extends JPanel
                             implements ActionListener, 
                                        PropertyChangeListener {

  private JProgressBar overallProgressBar;
  private JProgressBar currentProgressBar;
  private JButton startButton;
  private JTextArea taskOutput;
  private Task task;

  class Task extends SwingWorker<Void, Integer> {

    private final JProgressBar currentProgressBar;

    private Task(JProgressBar progressBar) {
      currentProgressBar = progressBar;
    }

    private void download(String urlString, int fileNumber, int total) {
      java.io.InputStream in = null;
      java.io.OutputStream out = null;

      try {
        taskOutput.append("Downloading file " + fileNumber + "...");

        java.net.URL url = new java.net.URL(urlString);

        java.net.HttpURLConnection httpConnection = (java.net.HttpURLConnection) (url.openConnection());

        long completeFileSize = httpConnection.getContentLength();
        in = httpConnection.getInputStream();
        out = new java.io.FileOutputStream("picture"+fileNumber+".png");

        final byte[] data = new byte[1024];
        long downloadedFileSize = 0;
        int count;
        while ((count = in.read(data, 0, 1024)) != -1) { 
          // --------------------------
          // TODO: Make downloads slower so you can watch things better, do not use in production code!
          try {
            Thread.sleep(200);
          } catch (InterruptedException ignore) {}
          // --------------------------

          downloadedFileSize += count;

          /* calculate progress (cheap variant, we assume that files are roughly the same size), another, more proper, way would be to prefetch all file sizes and give actual progress */
          final int currentProgress = (int) (((double)downloadedFileSize) / ((double)completeFileSize) * 100d );
          final int scaledCurrentProgress = currentProgress / total;
          final int overallProgress = (int) (((double)fileNumber/(double)total) * 100d);
          /* notifications of progress */
          setProgress(Math.min(scaledCurrentProgress + overallProgress,100));
          publish(Math.min(currentProgress,100));
          /* save downloaded data */        
          out.write(data, 0, count);
        } 

        taskOutput.append("done!\n");           
      } catch (FileNotFoundException e) {
        taskOutput.append("File not found: " + e);
      } catch (IOException e) {
        taskOutput.append("IO exception: " + e);
      } catch (Exception e) {
        taskOutput.append("Something went wrong: " + e);
      } finally {
        try {
          if (in != null) {
            in.close();
          }
          if (out != null) {
            out.close();
          }
        } catch (IOException e) {
          taskOutput.append("IO exception: " + e);
        }
      }
    }

    /*
     * Main task. Executed in background thread.
     */
    @Override
    public Void doInBackground() {
      // TODO: Probably this data would be given to the class in the constructor
      java.util.List<String> urlStrings = java.util.Arrays.asList(
                                            "http://imgs.xkcd.com/comics/tamagotchi_hive.png ", 
                                            "http://imgs.xkcd.com/comics/solar_system_questions.png ",
                                            "http://imgs.xkcd.com/comics/90s_kid.png",
                                            "http://imgs.xkcd.com/comics/xkcd_phone_3.png",
                                            "http://imgs.xkcd.com/comics/episode_vii.png");

      setProgress(0);

      int numberOfURLs = urlStrings.size();

      for (int i = 0; i < numberOfURLs; i++) {
        download(urlStrings.get(i), i, numberOfURLs);
      }

      return null;
    }

    /*
     * Handle data from publish(), i.e., current file progress
     */
    @Override
    protected void process(java.util.List<Integer> progressList) {
      final int progress = progressList.get(progressList.size() - 1);
      currentProgressBar.setValue(progress);
    }

    /*
     * Executed in event dispatching thread
     */
    @Override
    public void done() {
      setCursor(null); //turn off the wait cursor
      taskOutput.append("All files downloaded!\n");
    }
  } // end of class Task

  public ProgressBarDemo() {
    super(new BorderLayout());

    //Create the demo's UI.
    startButton = new JButton("Start");
    startButton.setActionCommand("start");
    startButton.addActionListener(this);

    overallProgressBar = new JProgressBar(0, 100);
    overallProgressBar.setValue(0);
    overallProgressBar.setStringPainted(true);

    currentProgressBar = new JProgressBar(0, 100);
    currentProgressBar.setValue(0);
    currentProgressBar.setStringPainted(true);

    taskOutput = new JTextArea(5, 20);
    taskOutput.setMargin(new Insets(5,5,5,5));
    taskOutput.setEditable(false);

    JPanel panel = new JPanel();
    panel.setLayout(new GridLayout(3,2));
    panel.add(new JLabel("Current File"));
    panel.add(currentProgressBar);
    panel.add(new JLabel("Overall Progress"));
    panel.add(overallProgressBar);
    panel.add(startButton);

    add(panel, BorderLayout.PAGE_START);
    add(new JScrollPane(taskOutput), BorderLayout.CENTER);
    setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
  }

  /**
   * Invoked when the user presses the start button.
   */
  public void actionPerformed(ActionEvent evt) {
    startButton.setEnabled(false);
    setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
    //Instances of javax.swing.SwingWorker are not reusuable, so
    //we create new instances as needed.
    task = new Task(currentProgressBar);
    task.addPropertyChangeListener(this);
    task.execute();
  }

  /**
   * Invoked when task's progress property changes.
   */
  public void propertyChange(PropertyChangeEvent evt) {
    if ("progress" == evt.getPropertyName()) {
      int progress = (Integer) evt.getNewValue();
      overallProgressBar.setValue(progress);
    } 
  }

  /**
   * Create the GUI and show it. As with all GUI code, this must run
   * on the event-dispatching thread.
   */
  private static void createAndShowGUI() {
    //Create and set up the window.
    JFrame frame = new JFrame("ProgressBarDemo");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    //Create and set up the content pane.
    JComponent newContentPane = new ProgressBarDemo();
    newContentPane.setOpaque(true); //content panes must be opaque
    frame.setContentPane(newContentPane);

    //Display the window.
    frame.pack();
    frame.setVisible(true);
  }

  public static void main(String[] args) {
    //Schedule a job for the event-dispatching thread:
    //creating and showing this application's GUI.
    javax.swing.SwingUtilities.invokeLater(new Runnable() {
      public void run() {
        createAndShowGUI();
      }
    });
  }
}

这篇关于java - 进度条和下载的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆