2010-07-25 3 views
3

Я использую BitmapFactory.decodeStream для загрузки изображения с URL-адреса в Android. Я хочу только загружать изображения ниже определенного размера, и в настоящее время я использую getContentLength, чтобы проверить это.Загрузить изображение с url в Android, только если оно будет

Однако мне говорят, что getContentLength не всегда обеспечивает размер файла, и в этих случаях я хотел бы остановить загрузку, как только узнаю, что файл слишком большой. Каков правильный способ сделать это?

Вот мой текущий код. В настоящее время я возвращаю null, если getContentLength не дает ответа.

HttpGet httpRequest = new HttpGet(new URL(urlString).toURI()); 
HttpClient httpClient = new DefaultHttpClient(); 
HttpResponse response = (HttpResponse) httpClient.execute(httpRequest); 
HttpEntity entity = response.getEntity(); 
BufferedHttpEntity bufHttpEntity = new BufferedHttpEntity(entity); 
final long contentLength = bufHttpEntity.getContentLength(); 
if ((contentLength >= 0 && (maxLength == 0 || contentLength < maxLength))) { 
    InputStream is = bufHttpEntity.getContent(); 
    Bitmap bitmap = BitmapFactory.decodeStream(is); 
    return new BitmapDrawable(bitmap); 
} else { 
    return null; 
} 

ответ

0

Вы должны использовать HttpHead для запроса HEAD, который похож на GET, но будет возвращать только заголовки. Если длина контента является удовлетворительной, вы можете сделать свой запрос GET для получения контента.

Большинство серверов должны обрабатывать HEAD-запросы без проблем, но иногда серверы приложений не ожидали его и будут вызывать ошибку. Просто то, что нужно знать.

ОБНОВЛЕНИЕ подумал, что я попытаюсь ответить на ваш фактический вопрос. Вероятно, вам придется прочитать данные в буфер промежуточного байта, прежде чем передавать данные в BitmapFactory.

InputStream is = bufHttpEntity.getContent(); 
ByteArrayOutputStream bytes = ByteArrayOutputStream(); 
byte[] buffer = new byte[128]; 
int read; 
int totalRead = 0; 
while ((read = is.read(buffer)) > 0) { 
    totalRead += read; 
    if (totalRead > TOO_BIG) { 
    // abort download. close connection 
    return null; 
    } 
    bytes.write(buffer, 0 read); 
} 

Unrelated, но помните, всегда вызывать consumeContent() на лицо после использования, так что HttpClient может повторно использовать соединение.

+0

Я знаю, что это не решает вашу проблему, когда сервер не предоставляет Content-Length, но я думаю, что если вы используете HttpGet, возможно, вы получаете контент, хотите ли вы этого или нет. Если он только получает его, когда вы читаете из потока, просто игнорируйте мой ответ! – Nick

+0

Спасибо, Ник. Я не знаю, будет ли использование HttpHead экономить пропускную способность, но в моем конкретном случае я предпочитаю хранить HTTP-запросы в minimun. – hpique

2

1. Вы также можете попробовать этот подход. Я считаю, что это не будет загружать контент для больших файлов

HttpURLConnection connection = (HttpURLConnection)new URL(url).openConnection(); 
int length=connection.getContentLength(); 

if(length<max){ 
    InputStream is = connection.getInputStream(); 
    BitmapFactory.decodeStream(is,null,null); 
} 

Это просто пример, вы можете также добавить проверку на -1 и что-нибудь еще. Этот подход эквивалентен тому, что вы делаете. Это еще один вариант для вас. Я просто знаю, что HttpURLConnection не извлекает контент, пока вы не начнете его читать из потока. Таким образом, этот код не будет загружать большие изображения. Я действительно не знаю, делает ли HttpClient то же самое или нет.

2. Почему на самом деле вы хотите пропустить большие файлы. Если вы беспокоитесь об декодировании OutOfMemory durung, можете взглянуть на это Strange out of memory issue while loading an image to a Bitmap object. Если вы примените inSampleSize, вы можете загрузить даже большие изображения. Задержка будет больше для больших изображений, но потребление памяти будет низким. Я разместил образец ListView здесь Lazy load of images in ListView. Он отображает изображения в ListView. Существуют изображения разных размеров. Не очень большие изображения, но в любом случае.

+0

Этот код неправильно обрабатывает случай, когда getContentLength возвращает -1. Кроме того, разве это не более простая версия того, что я делаю? Я хочу пропустить большие файлы, потому что эта логика выполняется для каждого элемента ListView. – hpique

+0

Обновлено мое сообщение с дополнительными разъяснениями. – Fedor

+0

Меня больше беспокоит скорость прокрутки, чем OutOfMemory. Как вы уже упоминали, задержка больше - вы уменьшаете большое изображение. – hpique

Смежные вопросы