简体   繁体   English

如何使用Java下载远程文件

[英]How to download a remote file using Java

I'm trying to download a single file from a web server (http or https) using as few third party libraries as possible. 我正在尝试使用尽可能少的第三方库从Web服务器(http或https)下载单个文件。

The method I've come up with is as follows: 我想出的方法如下:

private static final int BUFFER_SIZE = 8;

public static boolean download(URL url, File f) throws IOException {
    URLConnection conn = url.openConnection();
    conn.setDoOutput(true);

    FileOutputStream out = new FileOutputStream(f);
    BufferedInputStream in = new BufferedInputStream(conn.getInputStream());

    byte[] buffer;
    long dld = 0, expected = conn.getContentLengthLong(); // TODO expected will be -1 if the content length is unknown
    while (true) { // TODO fix endless loop if server timeout
        buffer = new byte[BUFFER_SIZE];
        int n = in.read(buffer);
        if (n == -1) break;
        else dld += n;
        out.write(buffer);
    }
    out.close();
    System.out.println(dld + "B transmitted to " + f.getAbsolutePath());
    return true;
}

However, it does by no means work as intended. 但是,它绝不会按预期工作。 I tried to download https://upload.wikimedia.org/wikipedia/commons/6/6d/Rubber_Duck_Florentijn_Hofman_Hong_Kong_2013d.jpg for example, the result was horrifying: 例如,我尝试下载https://upload.wikimedia.org/wikipedia/commons/6/6d/Rubber_Duck_Florentijn_Hofman_Hong_Kong_2013d.jpg ,结果令人恐惧:

For some reason I was able to view the picture in IrfanView but not in any other viewer, so this is a re saved version. 由于某种原因,我能够在IrfanView中查看图片,但无法在任何其他查看器中查看,因此这是重新保存的版本。

I tried messing with the buffer size or downloading other images but the results are more or less the same. 我尝试弄乱缓冲区大小或下载其他图像,但结果大致相同。

If I look at the file, there are entire parts of the content simply replaced with dots: 如果我看一下文件,内容的整个部分都只是用点代替:

I'm really lost on this one so thanks for any help :) 我真的迷失了这个,所以谢谢你的帮助:)

The problem occurs when there aren't 8 bytes of data to read. 当没有8个字节的数据要读取时,就会发生此问题。 This leaves part of the array filled with zeros, which is why you're seeing so many in your hex editor. 这使数组的一部分充满零,这就是为什么在十六进制编辑器中看到如此多的原因。

The solution is simple: replace out.write(buffer); 解决方案很简单:替换out.write(buffer); with out.write(buffer, 0, n); out.write(buffer, 0, n); . This tells the FileOutputStream to only read the bytes between indexes 0 and n . 这告诉FileOutputStream仅读取索引0n之间的字节。

Fixed code: 固定代码:

private static final int BUFFER_SIZE = 8;

public static boolean download(URL url, File f) throws IOException {
    URLConnection conn = url.openConnection();
    conn.setDoOutput(true);

    FileOutputStream out = new FileOutputStream(f);
    BufferedInputStream in = new BufferedInputStream(conn.getInputStream());

    // We can move the buffer declaration outside the loop
    byte[] buffer = new byte[BUFFER_SIZE];

    long dld = 0, expected = conn.getContentLengthLong(); // TODO expected will be -1 if the content length is unknown
    while (true) {
        int n = in.read(buffer);
        if (n == -1) break;
        else dld += n;
        out.write(buffer, 0, n);
    }
    out.close();
    System.out.println(dld + "B transmitted to " + f.getAbsolutePath());
    return true;
}

Try something like this to download pictures 试试这样的东西下载图片

public static byte[] download(String param) throws IOException {
    InputStream in = null;
    ByteArrayOutputStream out = null;

    try {
        URL url = new URL(param);
        HttpURLConnection con = (HttpURLConnection)url.openConnection(); 
        con.setConnectTimeout(120000);
        con.setReadTimeout(120000);
        con.setRequestMethod("GET");
        con.connect();
        in = new BufferedInputStream(con.getInputStream());
        out = new ByteArrayOutputStream();
        byte[] buf = new byte[1024];
        int n = 0;
        while (-1 != (n = in.read(buf))) {
            out.write(buf, 0, n);
        }

        return out.toByteArray();

    } finally {
        try {
            out.close();
        } catch (Exception e1) {

        }
        try {
            in.close();
        } catch (Exception e2) {

        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM