当我使用SwingWorker时为什么不下载我的图像,但是当我不这样做时下载?

时间:2017-07-21 02:25:26

标签: java debugging download swingworker

我正在创建一个进度条来监控图像下载。图像下载不起作用 - 它生成一个大小为0字节的文件。如果我将代码移动到没有SwingWorker的独立类,则图像下载有效。我已经玩了一段时间,但我仍然不知道自己做错了什么。两个代码块是相同的。任何提示将不胜感激!

使用SwingWorker进行图片下载(请注意doInBackground):

package download_progress_bar;

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

public class ProgressBar implements ActionListener, PropertyChangeListener {
    private JFrame frame;
    private JPanel gui;
    private JButton button;
    private JProgressBar progressBar;
    private SwingWorker<Void, Void> worker;
    private boolean done;

    public ProgressBar() {
        done = false;
        customizeFrame();
        createMainPanel();
        createProgressBar();
        createButton();
        addComponentsToFrame();
    }

    private void customizeFrame() {
        frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }

    private void createMainPanel() {
        gui = new JPanel();
        gui.setLayout(new BorderLayout());
    }

    private void createProgressBar() {
        progressBar = new JProgressBar(0, 100);
        progressBar.setStringPainted(true);  // renders a progress string
    }

    private void createButton()  {
        button = new JButton("Start download");
        button.addActionListener(this);
    }

    /**
     * Invoked when user clicks the button.
     */
    public void actionPerformed(ActionEvent evt) {
        button.setEnabled(false);
        // NOTE: Instances of javax.swing.SwingWorker are not reusable, 
        // so we create new instances as needed
        worker = new Worker();
        worker.addPropertyChangeListener(this);
        worker.execute();
    }

    class Worker extends SwingWorker<Void, Void> {
        /* 
         * Main task. Executed in worker thread.
         */
        @Override
        protected Void doInBackground() throws MalformedURLException {
            // Create a URL object for a given URL
            String src = "https://lh3.googleusercontent.com/l6JAkhvfxbP61_FWN92j4ulDMXJNH3HT1DR6xrE7MtwW-2AxpZl_WLnBzTpWhCuYkbHihgBQ=s640-h400-e365";
            URL url = new URL(src);
            // Open connection on the URL object

            try {
                HttpURLConnection connection = (HttpURLConnection) url.openConnection();

                // Always check response code first
                int responseCode = connection.getResponseCode();
                if (responseCode == HttpURLConnection.HTTP_OK) {
                    System.out.println(responseCode);

                    // Open input stream from connection
                    BufferedInputStream in = new BufferedInputStream(connection.getInputStream());
                    // Open output stream for file writing
                    BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream("cat.jpg"));

                    int bytesRead = - 1;
                    int totalBytesRead = 0;
                    int percentCompleted = 0;

                    while ((bytesRead = in.read()) != -1) {
                        out.write(bytesRead);
                        totalBytesRead += bytesRead;
                        percentCompleted = totalBytesRead * 100 / connection.getContentLength();

                        System.out.println("..." + percentCompleted);
                        this.setProgress(percentCompleted);
                    }

                    // Close streams
                    out.close();
                    in.close();
                }
            } catch (IOException ex) {
                System.out.println(ex);
                this.setProgress(0);
                cancel(true);
            }

            return null;
        }

        /*
         * Executed in event dispatching thread
         */
        @Override
        protected void done() {
            button.setEnabled(true);
            if (!isCancelled()) {
                System.out.println("File has been downloaded successfully!");
            } else {
                System.out.println("There was an error in downloading the file.");
            }
        }
    }

    /**
     * Invoked when task's progress property changes.
     */
    public void propertyChange(PropertyChangeEvent evt) {
        System.out.println(evt);
        // NOTE: By default two property states exist: "state" and "progress"
        if (evt.getPropertyName().equals("progress")) {
            int progress = (Integer) evt.getNewValue();
            progressBar.setValue(progress);
            System.out.println(String.format(
                    "Completed %d%% of task.\n", progress));
        }
    }

    private void addComponentsToFrame() {
        gui.add(progressBar, BorderLayout.CENTER);
        gui.add(button, BorderLayout.SOUTH);
        frame.add(gui);
        frame.pack();
    }

    public void activate() {
        frame.setVisible(true);
    }
}

使用独立Downloader课程进行图片下载(请注意download):

package download_progress_bar;

import java.net.*;
import java.io.*;

public class Downloader {
    public static void main(String[] args) throws IOException {
        download();
    }

    public static void download() throws IOException {
        // Create a URL object for a given URL
        String src = "https://lh3.googleusercontent.com/l6JAkhvfxbP61_FWN92j4ulDMXJNH3HT1DR6xrE7MtwW-2AxpZl_WLnBzTpWhCuYkbHihgBQ=s640-h400-e365";
        URL url = new URL(src);
        // Open connection on the URL object

        try {
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();

            // Always check response code first
            int responseCode = connection.getResponseCode();
            if (responseCode == HttpURLConnection.HTTP_OK) {
                System.out.println(responseCode);

                // Open input stream from connection
                BufferedInputStream in = new BufferedInputStream(connection.getInputStream());
                // Open output stream for file writing
                BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream("test.jpg"));

                int bytesRead = - 1;
                int totalBytesRead = 0;
                int percentCompleted = 0;

                while ((bytesRead = in.read()) != -1) {
                    out.write(bytesRead);
                    totalBytesRead += bytesRead;
                    percentCompleted = totalBytesRead * 100 / connection.getContentLength();

                    System.out.println("..." + percentCompleted);
                }

                // Close streams
                out.close();
                in.close();
            }
        } catch (IOException ex) {
            System.out.println(ex);
        }
    }
}

1 个答案:

答案 0 :(得分:2)

您应该在done()中致电get()。如果doInBackground引发异常,则get()会抛出ExecutionException,其原因是doInBackground的例外。

这样的事情:

@Override
protected void done() {
    button.setEnabled(true);
    try {
        if (!isCancelled()) {
            get();
            System.out.println("File has been downloaded successfully!");
            return;
        }
    } catch (InterruptedException x) {
        x.printStackTrace();
    } catch (ExecutionException x) {
        // This should print an IllegalArgumentException
        // if me theory (explained below) is correct.
        x.getCause().printStackTrace();
    }
    System.out.println("There was an error in downloading the file.");
}

我的理论是这个问题与这一行有关:

totalBytesRead += bytesRead;

由于bytesReadInputStream.read()的返回值,它实际上是一个数据字节,而不是读取的字节数。这对I / O没有明显影响,但它会破坏percentCompleted的值。这最终会将大于100的值传递给setProgress,从而引发异常。该行应为totalBytesRead++;

您可以通过前面对done()的修改验证我的理论。