Загрузить файл с помощью java apache commons?

Как я могу использовать библиотеку для загрузки файла и сохранения сохраненных байтов? Я попытался использовать

import static org.apache.commons.io.FileUtils.copyURLToFile;
public static void Download() {

        URL dl = null;
        File fl = null;
        try {
            fl = new File(System.getProperty("user.home").replace("\\", "/") + "/Desktop/Screenshots.zip");
            dl = new URL("http://ds-forums.com/kyle-tests/uploads/Screenshots.zip");
            copyURLToFile(dl, fl);
        } catch (Exception e) {
            System.out.println(e);
        }
    }

но я не могу отображать байты или индикатор выполнения. Какой метод следует использовать?

public class download {
    public static void Download() {
        URL dl = null;
        File fl = null;
        String x = null;
        try {
            fl = new File(System.getProperty("user.home").replace("\\", "/") + "/Desktop/Screenshots.zip");
            dl = new URL("http://ds-forums.com/kyle-tests/uploads/Screenshots.zip");
            OutputStream os = new FileOutputStream(fl);
            InputStream is = dl.openStream();
            CountingOutputStream count = new CountingOutputStream(os);
            dl.openConnection().getHeaderField("Content-Length");
            IOUtils.copy(is, os);//begin transfer

            os.close();//close streams
            is.close();//^
        } catch (Exception e) {
            System.out.println(e);
        }
    }

Ответы

Ответ 1

Если вы ищете способ получить общее количество байтов перед загрузкой, вы можете получить это значение из заголовка Content-Length в ответе http.

Если вы просто хотите получить окончательное количество байтов после загрузки, проще всего проверить размер файла, который вы просто пишете.

Однако, если вы хотите отобразить текущий ход загрузки нескольких байтов, вы можете расширить apache CountingOutputStream, чтобы обернуть FileOutputStream, чтобы каждый раз, когда методы write вызывались, он подсчитывает количество байты, проходящие и обновляющие индикатор выполнения.

Обновление

Вот простая реализация DownloadCountingOutputStream. Я не уверен, что вы знакомы с использованием ActionListener или нет, но это полезный класс для реализации GUI.

public class DownloadCountingOutputStream extends CountingOutputStream {

    private ActionListener listener = null;

    public DownloadCountingOutputStream(OutputStream out) {
        super(out);
    }

    public void setListener(ActionListener listener) {
        this.listener = listener;
    }

    @Override
    protected void afterWrite(int n) throws IOException {
        super.afterWrite(n);
        if (listener != null) {
            listener.actionPerformed(new ActionEvent(this, 0, null));
        }
    }

}

Это пример использования:

public class Downloader {

    private static class ProgressListener implements ActionListener {

        @Override
        public void actionPerformed(ActionEvent e) {
            // e.getSource() gives you the object of DownloadCountingOutputStream
            // because you set it in the overriden method, afterWrite().
            System.out.println("Downloaded bytes : " + ((DownloadCountingOutputStream) e.getSource()).getByteCount());
        }
    }

    public static void main(String[] args) {
        URL dl = null;
        File fl = null;
        String x = null;
        OutputStream os = null;
        InputStream is = null;
        ProgressListener progressListener = new ProgressListener();
        try {
            fl = new File(System.getProperty("user.home").replace("\\", "/") + "/Desktop/Screenshots.zip");
            dl = new URL("http://ds-forums.com/kyle-tests/uploads/Screenshots.zip");
            os = new FileOutputStream(fl);
            is = dl.openStream();

            DownloadCountingOutputStream dcount = new DownloadCountingOutputStream(os);
            dcount.setListener(progressListener);

            // this line give you the total length of source stream as a String.
            // you may want to convert to integer and store this value to
            // calculate percentage of the progression.
            dl.openConnection().getHeaderField("Content-Length");

            // begin transfer by writing to dcount, not os.
            IOUtils.copy(is, dcount);

        } catch (Exception e) {
            System.out.println(e);
        } finally {
            IOUtils.closeQuietly(os);
            IOUtils.closeQuietly(is);
        }
    }
}

Ответ 2

commons-io имеет IOUtils.copy(inputStream, outputStream). Итак:

OutputStream os = new FileOutputStream(fl);
InputStream is = dl.openStream();

IOUtils.copy(is, os);

И IOUtils.toByteArray(is) может использоваться для получения байтов.

Получение общего количества байтов - это другая история. Потоки не дают вам никакого общего - они могут предоставить вам только то, что доступно в потоке. Но поскольку это поток, он может иметь больше прихода.

Вот почему у http есть свой особый способ указать общее количество байтов. Он находится в заголовке ответа Content-Length. Поэтому вам нужно вызвать url.openConnection(), а затем вызвать getHeaderField("Content-Length") в объекте URLConnection. Он вернет количество байтов в виде строки. Затем используйте Integer.parseInt(bytesString), и вы получите общее количество.