Не может захватить достижения по http загрузке файла POST (Android)

Я разрабатываю приложение для Android, которое позволяет пользователю загрузить файл на сервисы как Twitpic и другие. Загрузка THE POST сделана без любых внешних библиотек и работает просто великолепно. Моя единственная проблема, что я не могу захватить прогресс, потому что вся загрузка сделана, когда я получаю ответ, не при записи байтов в outputstream. Вот то, что я делаю:

URL url = new URL(urlString); 
HttpURLConnection conn = (HttpURLConnection) url.openConnection(); 
conn.setDoInput(true); 
conn.setDoOutput(true); 
conn.setUseCaches(false); 
conn.setRequestMethod("POST"); 
conn.setRequestProperty("Connection", "Keep-Alive"); 
conn.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary); 
DataOutputStream dos = new DataOutputStream(conn.getOutputStream());

Затем я пишу данные формы в DOS, которая не так важна здесь, теперь. После этого я пишу сами данные файла (читающий из "в", который является InputStream данных, которые я хочу отправить):

while ((bytesAvailable = in.available()) > 0)
{ 
 bufferSize = Math.min(bytesAvailable, maxBufferSize);
 byte[] buffer = new byte[bufferSize];
 bytesRead = in.read(buffer, 0, bufferSize);
 dos.write(buffer, 0, bytesRead);
} 

После этого я отправляю многослойные данные формы для указания на конец файла. Затем я закрываю потоки:

in.close(); 
dos.flush(); 
dos.close(); 

Это все превосходные работы, без проблем до сих пор. Моя проблема, однако, что целый процесс до этой точки берет об одной или двух секундах, неважно, насколько большой файл. Сама загрузка, кажется, происходит, когда я считал ответ:

DataInputStream inStream = new DataInputStream(conn.getInputStream());

Это занимает несколько секунд или минут, в зависимости от того, насколько большой файл и как быстро интернет-соединение. Мои вопросы теперь состоят в том: 1) Почему загрузки не происходит, когда я пишу байты в "DOS"? 2) Как я могу захватить прогресс для показа диалогового окна прогресса во время загрузки, когда все это происходит сразу?

/ РЕДАКТИРОВАНИЕ: 1) я установил Довольную Длину в заголовке, который изменяет проблему немного, но ни в коем случае не решает ее: Теперь целое содержание загружается после того, как последний байт записан в поток. Так, это не изменяет ситуацию, что Вы не можете захватить прогресс, потому что снова, данные записаны сразу. 2) я попробовал MultipartEntity в Apache HttpClient v4. Там у Вас нет OutputStream вообще, потому что все данные записаны при выполнении запроса. Таким образом, снова нет никакого способа захватить прогресс.

Есть ли кто-либо там, у кого есть какая-либо другая идея, как захватить процесс в многослойной загрузке / загрузке формы?

17
задан Manuel 12 July 2010 в 16:52
поделиться

1 ответ

В последние дни я довольно много пробовал и думаю, что у меня есть ответ на начальный вопрос:

Невозможно получить прогресс, используя HttpURLConnection, потому что есть ошибка / необычное поведение в Android: http://code.google.com/p/android/issues/detail?id=3164#c6

Это будет фиксированный пост Фройо, чего не стоит ждать ...

Итак, единственный другой вариант, который я нашел, - это использовать Apache HttpClient. Ответ , связанный papleu , правильный, но он относится к общей Java.Используемые там классы больше не доступны в Android (HttpClient 3.1 когда-то входил в состав SDK). Итак, что вы можете сделать, так это добавить библиотеки из HttpClient 4 (в частности, apache-mime4j-0.6.jar и httpmime-4.0.1.jar) и использовать комбинацию первого ответа (от Tuler) и последнего ответа (от Hamy ):

import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.Charset;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntity;

public class CountingMultipartEntity extends MultipartEntity {

    private final ProgressListener listener;

    public CountingMultipartEntity(final ProgressListener listener) {
        super();
        this.listener = listener;
    }

    public CountingMultipartEntity(final HttpMultipartMode mode, final ProgressListener listener) {
        super(mode);
        this.listener = listener;
    }

    public CountingMultipartEntity(HttpMultipartMode mode, final String boundary,
            final Charset charset, final ProgressListener listener) {
        super(mode, boundary, charset);
        this.listener = listener;
    }

    @Override
    public void writeTo(final OutputStream outstream) throws IOException {
        super.writeTo(new CountingOutputStream(outstream, this.listener));
    }

    public static interface ProgressListener {
        void transferred(long num);
    }

    public static class CountingOutputStream extends FilterOutputStream {

        private final ProgressListener listener;
        private long transferred;

        public CountingOutputStream(final OutputStream out,
                final ProgressListener listener) {
            super(out);
            this.listener = listener;
            this.transferred = 0;
        }


        public void write(byte[] b, int off, int len) throws IOException {
            out.write(b, off, len);
            this.transferred += len;
            this.listener.transferred(this.transferred);
        }

        public void write(int b) throws IOException {
            out.write(b);
            this.transferred++;
            this.listener.transferred(this.transferred);
        }
    }
}

Это работает с HttpClient 4, но недостатком является то, что мой apk теперь имеет размер 235 КБ (это было 90 КБ, когда я использовал многостраничную загрузку, описанную в моем вопросе) и, что еще хуже, размер установленного приложения 735 кб (около 170 кб ранее). Это действительно ужасно. Только для того, чтобы добиться прогресса во время загрузки, размер приложения теперь более чем в 4 раза больше, чем был раньше.

20
ответ дан 30 November 2019 в 13:40
поделиться
Другие вопросы по тегам:

Похожие вопросы: