使用Java通过HTTP下载长度未知的文件

6

我想用Java下载一个HTTP查询,但是当下载时我下载的文件大小不确定。

我认为这应该是很标准的,所以我搜索并找到了一个相应的代码片段:http://snipplr.com/view/33805/

但是它有一个关于contentLength变量的问题。因为长度未知,所以我得到-1。这会导致一个错误。当我省略关于contentLength的整个检查时,那就意味着我总是要使用最大的缓冲区。

但问题在于文件还没有准备好。所以刷新只被部分填充,文件的某些部分丢失了。

如果您尝试下载像http://overpass-api.de/api/interpreter?data=area%5Bname%3D%22Hoogstade%22%5D%3B%0A%28%0A++node%28area%29%3B%0A++%3C%3B%0A%29+%3B%0Aout+meta+qt%3B那样的链接,您会注意到错误,并且当您始终下载最大缓冲区以省略错误时,即使您下载的是几个GB的大文件,也会得到一个损坏的XML文件。

有没有办法只下载文件的准备好的部分?我希望它能够下载大文件(最多几GB)。

1个回答

19

这应该可以工作,我测试过并且对我有效:

void downloadFromUrl(URL url, String localFilename) throws IOException {
    InputStream is = null;
    FileOutputStream fos = null;

    try {
        URLConnection urlConn = url.openConnection();//connect

        is = urlConn.getInputStream();               //get connection inputstream
        fos = new FileOutputStream(localFilename);   //open outputstream to local file

        byte[] buffer = new byte[4096];              //declare 4KB buffer
        int len;

        //while we have availble data, continue downloading and storing to local file
        while ((len = is.read(buffer)) > 0) {  
            fos.write(buffer, 0, len);
        }
    } finally {
        try {
            if (is != null) {
                is.close();
            }
        } finally {
            if (fos != null) {
                fos.close();
            }
        }
    }
}

如果您希望此操作在后台运行,只需在线程中调用它:

Thread download = new Thread(){
    public void run(){
        URL url= new URL("http://overpass-api.de/api/interpreter?data=area%5Bname%3D%22Hoogstade%22%5D%3B%0A%28%0A++node%28area%29%3B%0A++%3C%3B%0A%29+%3B%0Aout+meta+qt%3B");
        String localFilename="mylocalfile"; //needs to be replaced with local file path
        downloadFromUrl(url, localFilename);
    }
};
download.start();//start the thread

我注意到真正的问题是在这种情况下file.seek命令没有正确工作。它没有找到文件的结尾,因此覆盖了其中的一部分。使用FileOutputStream解决了这个问题(在我已经删除错误代码之后)。 - sanderd17

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接