【问题标题】:Download file using java apache commons?使用java apache commons下载文件?
【发布时间】:2011-01-15 07:39:41
【问题描述】:

如何使用该库下载文件并打印保存的字节数?我尝试使用

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);
        }
    }

【问题讨论】:

    标签: java apache-commons-io


    【解决方案1】:

    如果您正在寻找一种方法来获取下载前的总字节数,您可以从 http 响应中的 Content-Length 标头中获取此值。

    如果您只想要下载后的最终字节数,最简单的方法是检查您刚刚写入的文件大小。

    但是,如果您想显示已下载多少字节的当前进度,您可能需要扩展 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);
            }
        }
    }
    

    【讨论】:

    • 如何扩展 apache 来使用它? fl = new File(System.getProperty("user.home").replace("\\", "/") + "/Desktop/Scr​​eenshots.zip"); dl = new URL("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);//开始传输我做对了吗?
    • 您介意将上面的代码附加到您的问题中吗?很难阅读。我会尽力提供帮助。
    • @Kyle 已更新。我希望你喜欢这个答案。
    • 顺便说一句,dl.openConnection() 将打开一个新连接以及 dl.openStream()。你应该重用连接,不要再次打开它,因为如果目标的内容是动态生成的,你可能会得到不同的内容长度。
    • 哇,非常感谢!我很佩服!不过,我对进度条有一个小问题。我是否通过progressBar.setValue 设置进度条的值?如果是这样,我无法访问下载的字节并将该值转换为内容长度的百分比。在你做了这个漂亮的 sn-p 之后,我真的很讨厌问这些愚蠢的问题。我很感激。 (我试图做的是从下载的字节中减去内容长度,然后做数学运算符来获取 % 来设置进度条。这是正确的方法吗?)
    【解决方案2】:

    commons-ioIOUtils.copy(inputStream, outputStream)。所以:

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

    IOUtils.toByteArray(is) 可用于获取字节。

    获取总字节数是另一回事。流不会给你任何总数——它们只能给你当前在流中可用的东西。但由于它是一个流,它可以有更多的来。

    这就是为什么http有它特殊的方式来指定总字节数。它位于响应标头Content-Length 中。所以你必须调用url.openConnection(),然后在URLConnection 对象上调用getHeaderField("Content-Length")。它将返回字节数作为字符串。然后使用Integer.parseInt(bytesString),你会得到你的总数。

    【讨论】:

    • 嗯.. 有没有办法显示从该流下载的字节?我正在寻找,但我没有看到方法。感谢您的回复。
    • 顺便说一句,字节本身,还是它们的数量?
    • 下载的总字节数,如果这就是计数的意思?抱歉,我还是 java 新手。
    • 太棒了。谢谢,我希望我能在标签中显示当前下载的字节数!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-04
    • 2013-10-18
    • 2018-09-17
    • 1970-01-01
    • 1970-01-01
    • 2015-01-24
    相关资源
    最近更新 更多