Как скачать удаленный файл с помощью Java - PullRequest
1 голос
/ 06 мая 2019

Я пытаюсь загрузить один файл с веб-сервера (http или https), используя как можно меньше сторонних библиотек.

Метод, который я придумал, следующий:

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

Однако это ни в коем случае не работает так, как задумано. Я пытался загрузить https://upload.wikimedia.org/wikipedia/commons/6/6d/Rubber_Duck_Florentijn_Hofman_Hong_Kong_2013d.jpg, например, результат был ужасным:

По какой-то причине мне удалось просмотреть изображение в IrfanView, но не в каком-либо другом средстве просмотра, так что это восстановленная версия.

Я попытался изменить размер буфера или загрузить другие изображения, но результаты более или менее совпадают.

Если я посмотрю на файл, то все части содержимого будут просто заменены точками:

Я действительно потерян на этом, так что спасибо за любую помощь:)

Ответы [ 2 ]

4 голосов
/ 06 мая 2019

Проблема возникает, когда нет 8 байтов данных для чтения.Это оставляет часть массива заполненной нулями, вот почему вы видите так много в вашем шестнадцатеричном редакторе.

Решение простое: замените out.write(buffer); на out.write(buffer, 0, n);.Это говорит FileOutputStream, что он читает только байты между индексами 0 и n.

Фиксированный код:

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;
}
1 голос
/ 06 мая 2019

Попробуйте что-нибудь подобное, чтобы загрузить картинки

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) {

        }
    }
}
...