Outofmemoryerror ByteArrayOutputStream отправляет большой файл в WS

Я отправляю видео в веб-сервис и работает нормально с видео размером менее 10 МБ, если видео составляет около 12 МБ, выведите меня из ошибки:

Это мой код:

 FileInputStream fileInputStream = new FileInputStream(fichero);

                int bytesAvailable = fileInputStream.available();
                int maxBufferSize = 1024 * 1024 * 2;
                int bufferSize = Math.min(bytesAvailable, maxBufferSize);
                byte[] buffer = new byte[bufferSize];

                int bytesRead = fileInputStream.read(buffer, 0, bufferSize);

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

                    // nuevos
                    bytesRead = fileInputStream.read(buffer, 0, bufferSize);
                    // esto es nuevo
                    dos.write(buffer, 0, bufferSize);
                    // ya no es nuevo
                }

Я думаю, что это потому, что я буферизирую все видео, но я не знаю, как отправить это без сохранения в буфере.

Это ошибка стека:

08-31 08:54:20.925: E/AndroidRuntime(18476): Caused by: java.lang.OutOfMemoryError
08-31 08:54:20.925: E/AndroidRuntime(18476):    at java.io.ByteArrayOutputStream.expand(ByteArrayOutputStream.java:91)
08-31 08:54:20.925: E/AndroidRuntime(18476):    at java.io.ByteArrayOutputStream.write(ByteArrayOutputStream.java:216)
08-31 08:54:20.925: E/AndroidRuntime(18476):    at org.apache.harmony.luni.internal.net.www.protocol.http.RetryableOutputStream.write(RetryableOutputStream.java:60)
08-31 08:54:20.925: E/AndroidRuntime(18476):    at java.io.DataOutputStream.write(DataOutputStream.java:99)
08-31 08:54:20.925: E/AndroidRuntime(18476):    at com.reparalia.movilidad.AdjuntarFicheros$SubeFichero.doInBackground(AdjuntarFicheros.java:702)
08-31 08:54:20.925: E/AndroidRuntime(18476):    at com.reparalia.movilidad.AdjuntarFicheros$SubeFichero.doInBackground(AdjuntarFicheros.java:1)

Строка 702 - это dos.write(buffer, 0, bufferSize);

Есть ли способ отправить видео? Спасибо

3 ответа

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

  1. Используйте размер буфера, указанный конструктором, или
  2. простираться ByteArrayOutputStream и переопределите методы записи, чтобы перераспределение было более выгодным для вашего потока.

Это происходит потому, что - если ни setFixedLengthStreamingMode(int), когда длина тела заранее известна, ни setChunkedStreamingMode(int) не установлены. В этом случае HttpURLConnection вынужден буферизовать все тело запроса в памяти перед его передачей, тратя впустую (и, возможно, исчерпывая) кучу и увеличивая задержку. Очень хорошо объяснено в ссылке - http://developer.android.com/reference/java/net/HttpURLConnection.html

Пожалуйста, добавьте следующую строку в ваш код - HttpUrlConnectionObject. setChunkedStreamingMode (maxBufferSize); для системного значения по умолчанию установлено 0 HttpUrlConnectionObject.setChunkedStreamingMode(0);

Это работает для меня.

Вместо того, чтобы писать код для копирования потока самостоятельно, вы можете попытаться использовать класс библиотеки для этого.

В Guava доступен класс ByteStreams. Если вы человек типа Commons IO, есть IOUtils.

В IOUtils ваш код будет выглядеть примерно так:

FileInputStream fileInputStream = new FileInputStream(fichero);
OutputStream dos = ...
IOUtils.copy(fileInputStream, dos);

Я упустил необходимую обработку исключений и закрытие потока.

Другие вопросы по тегам