Неожиданный результат от HttpURLConnection - чтение удаленного двоичного файла

StackOverflow https://stackoverflow.com/questions/611346

  •  03-07-2019
  •  | 
  •  

Вопрос

Я пытаюсь прочитать удаленный двоичный файл (скажем, изображение) из Интернета следующим образом:

HttpURLConnection connection = (HttpURLConnection) myUrl.openConnection(); //myUrl - URL object pointing for some location
if(connection.getResponseCode() == 200){
    File temp = File.createTempFile("blabla", fileName); //fileName - string name of file
    FileOutputStream out = new FileOutputStream(temp);
    int fileSize = Integer.parseInt(connection.getHeaderField("content-length"));
    int counter = 0;
    DataInputStream in = new DataInputStream(connection.getInputStream());
    byte ch[] = new byte[1024];
    System.out.println(counter);
    while((counter += in.read(ch)) > 0){
        out.write(ch);
        if(counter == fileSize){
            out.close();
            break;
        }
    }
}

Локально или с локальным веб-сервером (localhost) это работает отлично.

Но.Тогда myUrl - это URL файла на каком-нибудь удаленном веб-сервере - он возвращает неожиданные результаты.Например, из источников данных файлов кажется, что он повторяет некоторые пакеты (я думаю, из-за повреждения предыдущих или чего-то еще), и результирующий файл обычно примерно на 10% больше исходного из-за этого повторения.Таким образом, файл поврежден и не может быть корректно открыт с помощью программы просмотра изображений.

Как я могу решить эту проблему?

Это было полезно?

Решение

read необязательно считывает весь буфер (особенно если он находится в конце потока).

Так что измените свой цикл:

for (;;) {
    int len = in.read(ch);
    if (len == -1) {
        break;
    }
    out.write(ch, 0, len);
}

Возможно, поместите этот код куда-нибудь в метод.

Также обратите внимание:

  • Нет никакого смысла в использовании DataInputStream здесь (хотя readFully часто бывает полезно).
  • Всегда закрывайте ресурс (например, потоки) с помощью обычной идиомы:

    final Resource resource = acquire();
    try {
        use(resource);
    } finally {
        resource.close();
    }
    
  • Вероятно, это не будет иметь большого значения, но размер буфера 1024 немного маловат.Я склонен по умолчанию использовать значение 8192 произвольно.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top