Intereting Posts
Android: Как настраивать-объявить пространство имен XML в styles.xml? Как использовать getListView () в действии? Android-тестирование смс с эмулятора Храните камеру libgdx внутри границ при панорамировании и масштабировании Как я могу правильно вызвать startIntentSenderForResult в службе? Как воспроизводить видео на YouTube в приложении для Android? Проект Android, ссылающийся на «нормальный» проект java в eclipse, поскольку обновление инструментов sdk 17 Как установить версию приложения для Android по номеру сборки в Jenkins? КлассNotFoundException после обновления ADT Robolectric test ListView не обновляется после изменения стоимости адаптера Как удалить приложение из списка последних приложений? Как исправить IncompatibleClassChangeError во время Android Jackson Parsing, используя аннотации в Android Lollipop? Голосовая команда стекла в ближайшем матче из данного списка Окно Eclipse Logcat отключает следы стека исключений Неявное намерение удалить приложение?

Как я могу получить размер файла во время загрузки с URL-адреса (используя http-соединение)?

Я работаю над проектом, который загружает файл с помощью http-соединения. Я показываю горизонтальный индикатор выполнения с индикатором состояния выполнения во время загрузки. Моя функция выглядит так:

....... try { InputStream myInput = urlconnect.getInputStream(); BufferedInputStream buffinput = new BufferedInputStream(myInput); ByteArrayBuffer baf = new ByteArrayBuffer(capacity); int current = 0; while((current = buffinput.read()) != -1) { baf.append((byte) current); } File outputfile = new File(createRepertory(app, 0), Filename); FileOutputStream myOutPut = new FileOutputStream(outputfile); myOutPut.write(baf.toByteArray()); ... } 

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

 progressBarStatus = ((int) downloadFileHttp(url, app) * 100)/sizefile; 

Long downloadFileHttp (.., ..) – это имя моей функции.

Я уже пытаюсь получить его с помощью outputfile.length, но его значение равно «1», возможно, это количество файлов, которые я пытаюсь загрузить.

Есть ли способ понять это?

ОБНОВЛЕНИЕ 1

У меня нет ни одной темы, которая позволила бы мне понять это. В настоящее время у меня есть горизонтальный индикатор выполнения, который отображает только 0 и 100% без промежуточных значений. Я думаю о другом подходе. Если я знаю скорость моего Wi-Fi и размер файла, я могу определить время загрузки.

Я знаю, что могу получить часть информации о моем Wi-Fi-соединении и размер моего файла для загрузки.

Кто-нибудь уже работал или имеет на нем нить?

Solutions Collecting From Web of "Как я могу получить размер файла во время загрузки с URL-адреса (используя http-соединение)?"

AsyncTask может быть идеальным решением для вас:

 private class DownloadFileTask extends AsyncTask<URL, Integer, Long> { protected Long doInBackground(URL... urls) { Url url = urls[0]; //connect to url here ....... try { InputStream myInput = urlconnect.getInputStream(); BufferedInputStream buffinput = new BufferedInputStream(myInput); ByteArrayBuffer baf = new ByteArrayBuffer(capacity); int current = 0; while((current = buffinput.read()) != -1) { baf.append((byte) current); //here you can send data to onProgressUpdate publishProgress((int) (((float)baf.length()/ (float)sizefile) * 100)); } File outputfile = new File(createRepertory(app, 0), Filename); FileOutputStream myOutPut = new FileOutputStream(outputfile); myOutPut.write(baf.toByteArray()); ... } protected void onProgressUpdate(Integer... progress) { //here you can set progress bar in UI thread progressBarStatus = progress; } 

}

Для запуска вызова AsyncTask в вашем методе

 new DownloadFileTask().execute(url); 

Я предполагаю, что вы используете HttpURLConnection . В этом случае вам нужно вызвать метод getContentLength() для urlconnect .

Однако серверу не требуется отправлять допустимую длину контента, поэтому вы должны быть готовы к тому, чтобы он был -1.

Проверьте заголовок Content-Length на ответ. Он должен быть установлен. Все основные HTTP-серверы используют этот заголовок.

В спецификациях HTTP 1.1 данные отклика chunk должны быть отброшены в несколько раундов. По сути, длина контента равна -1 в ответном фрагменте, поэтому мы не можем использовать метод availble в Inputstream. BTW, метод Inputstream.availble является только стабильным, чтобы получить длину содержимого в ByteArrayInputStream .

Если вы просто хотите получить общую длину, вам нужно рассчитать ее самостоятельно в каждом раунде чтения. См. Класс IOUtils в IOUtils apache commons-io, как IOUtils ниже:

 //----------------------------------------------------------------------- /** * Copy bytes from an <code>InputStream</code> to an * <code>OutputStream</code>. * <p> * This method buffers the input internally, so there is no need to use a * <code>BufferedInputStream</code>. * <p> * Large streams (over 2GB) will return a bytes copied value of * <code>-1</code> after the copy has completed since the correct * number of bytes cannot be returned as an int. For large streams * use the <code>copyLarge(InputStream, OutputStream)</code> method. * * @param input the <code>InputStream</code> to read from * @param output the <code>OutputStream</code> to write to * @return the number of bytes copied * @throws NullPointerException if the input or output is null * @throws IOException if an I/O error occurs * @throws ArithmeticException if the byte count is too large * @since Commons IO 1.1 */ public static int copy(InputStream input, OutputStream output) throws IOException { long count = copyLarge(input, output); if (count > Integer.MAX_VALUE) { return -1; } return (int) count; } /** * Copy bytes from a large (over 2GB) <code>InputStream</code> to an * <code>OutputStream</code>. * <p> * This method buffers the input internally, so there is no need to use a * <code>BufferedInputStream</code>. * * @param input the <code>InputStream</code> to read from * @param output the <code>OutputStream</code> to write to * @return the number of bytes copied * @throws NullPointerException if the input or output is null * @throws IOException if an I/O error occurs * @since Commons IO 1.3 */ public static long copyLarge(InputStream input, OutputStream output) throws IOException { byte[] buffer = new byte[DEFAULT_BUFFER_SIZE]; long count = 0; int n = 0; while (-1 != (n = input.read(buffer))) { output.write(buffer, 0, n); count += n; } return count; } 

Если вы хотите проверить ход загрузки, вам необходимо выполнить обратный вызов в каждом раунде read от входа InputStream до вывода OutputStream в ходе перехода на диск. В обратном вызове вы можете скопировать кусок данных и добавить сумму к счетчику, который предназначен для доступности для вашей функциональности progressbar. Он немного сложный

Просто. Ниже код:

 try { URL url = new URL(yourLinkofFile); URLConnection conn = url.openConnection(); conn.connect(); totalFileSize = conn.getContentLength(); } catch (Exception e) { Log.e(TAG, "ERROR: " + e.toString()); } 

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

У вас есть несколько подходов для решения этой проблемы:

1.) В вашем пункте состояния выполнения есть обратный вызов, который позволит вам установить значение и вызвать этот метод каждый раз, когда вы обновите свой счет в своем потоке загрузки. 2.) Поместите значение в какое-то поле, доступное для обоих потоков (потенциально небезопасное).

Если бы это был я, то в моем баровом элементе прогресса у меня был бы метод, который позволил бы обновить прогресс с некоторой ценностью. Затем я бы назвал этот метод из моего потока, который загружает файл.

Таким образом, в основном User -> Clicks some download button -> Handler вызывает метод, чтобы начать загрузку, передавая обратный вызов методу выполнения строки обновления -> Загрузка потока вызывает метод в каждом итеративном цикле с обновленным процентом.

Я думаю, что ты слишком усложняешь свою жизнь 🙂

Во-первых: поскольку progressBarStatus = ((int) downloadFileHttp(url, app) * 100)/sizefile; Всегда либо 0, либо 100, возможно, вы неправильно вычисляете значение. Вы не размещали весь метод там, но не забывайте, что вы имеете дело с int, поэтому файл размера всегда является int, а деление на более высокий или равный размерному файлу всегда возвращается 0 или 1. Я подозреваю, что это Направление, в котором вам нужно заглянуть … Кроме того, я не вижу в вашем коде, где вы обновляете панель прогресса после прочтения промежуточного байта.

Во-вторых: Я думаю, что было бы более эффективно, если бы вы читали куски. Чтение более эффективно, и вам не нужно уведомлять поток пользовательского интерфейса для каждого загруженного байта. Ответ Адамски из этой темы может помочь вам. Просто используйте меньший массив байтов. Обычно я использую 256 (3G) или 512 (Wi-Fi), но, возможно, вам не нужно уделять много внимания деталям. Итак, как только вы получите новый массив, прочитайте, подсчитайте общее количество прочитанных байтов, сообщите об этом пользовательскому интерфейсу и продолжайте чтение до конца потока.

В-третьих: Задайте progressBar.setMax() перед загрузкой в ​​sizeFile, правильно вычислите загруженный номер байта на основе комментария от «First», а затем вызовите setProgress с этим вычисленным номером. Просто не забудьте обновить панель прогресса в потоке пользовательского интерфейса. AsyncTask имеет отличный механизм, который поможет вам в этом.

Удачи!

Ну, это должно помочь вам

 URLConnection connection = servletURL.openConnection(); BufferedInputStream buff = new BufferedInputStream(connection .getInputStream()); ObjectInputStream input = new ObjectInputStream(buff ); int avail = buff .available(); System.out.println("Response content size = " + avail);