java.net.URL leer el flujo a byte

Estoy tratando de leer una imagen de una URL (con el paquete java java.net.URL ) en un byte []. “Todo” funciona bien, excepto que el contenido no se lee completamente de la transmisión (la imagen está corrupta, no contiene todos los datos de imagen) … La matriz de bytes se está conservando en una base de datos (BLOB). Realmente no sé cuál es el enfoque correcto, tal vez me puedas dar un consejo 🙂

Este es mi primer enfoque (código formateado, elimina información innecesaria …):

URL u = new URL("http://localhost:8080/images/anImage.jpg"); int contentLength = u.openConnection().getContentLength(); Inputstream openStream = u.openStream(); byte[] binaryData = new byte[contentLength]; openStream.read(binaryData); openStream.close(); 

Mi segundo enfoque fue este (como verán que la longitud de contenido se va a buscar de otra manera):

 URL u = new URL(content); openStream = u.openStream(); int contentLength = openStream.available(); byte[] binaryData = new byte[contentLength]; openStream.read(binaryData); openStream.close(); 

Ambos resultados del código en una imagen dañada … Ya leí esta publicación de stackoverflow

No hay garantía de que la duración del contenido que le proporcionen sea realmente correcta. Pruebe algo similar a lo siguiente:

 ByteArrayOutputStream baos = new ByteArrayOutputStream(); InputStream is = null; try { is = url.openStream (); byte[] byteChunk = new byte[4096]; // Or whatever size you want to read in at a time. int n; while ( (n = is.read(byteChunk)) > 0 ) { baos.write(byteChunk, 0, n); } } catch (IOException e) { System.err.printf ("Failed while reading bytes from %s: %s", url.toExternalForm(), e.getMessage()); e.printStackTrace (); // Perform any other exception handling that's appropriate. } finally { if (is != null) { is.close(); } } 

A continuación, tendrá los datos de imagen en baos , desde los que puede obtener una matriz de bytes llamando a baos.toByteArray() .

Este código no ha sido probado (lo acabo de escribir en el recuadro de respuestas), pero es una aproximación razonablemente cercana a lo que creo que está buscando.

Simplemente extendiendo la respuesta de Barnards con commons-io. Respuesta separada porque no puedo formatear el código en los comentarios.

 InputStream is = null; try { is = url.openStream (); byte[] imageBytes = IOUtils.toByteArray(is); } catch (IOException e) { System.err.printf ("Failed while reading bytes from %s: %s", url.toExternalForm(), e.getMessage()); e.printStackTrace (); // Perform any other exception handling that's appropriate. } finally { if (is != null) { is.close(); } } 

http://commons.apache.org/io/api-1.4/org/apache/commons/io/IOUtils.html#toByteArray(java.io.InputStream)

Aquí hay una solución limpia:

 private byte[] downloadUrl(URL toDownload) { ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); try { byte[] chunk = new byte[4096]; int bytesRead; InputStream stream = toDownload.openStream(); while ((bytesRead = stream.read(chunk)) > 0) { outputStream.write(chunk, 0, bytesRead); } } catch (IOException e) { e.printStackTrace(); return null; } return outputStream.toByteArray(); } 
 byte[] b = IOUtils.toByteArray((new URL( )).openStream()); //idiom 

Sin embargo, tenga en cuenta que esa secuencia no se cierra en el ejemplo anterior.

si quieres un fragmento (de 76 caracteres) (usando el códec de commons) …

 byte[] b = Base64.encodeBase64(IOUtils.toByteArray((new URL( )).openStream()), true); 

Estoy muy sorprendido de que nadie aquí haya mencionado el problema de la conexión y el tiempo de espera de lectura . Podría suceder (especialmente en Android y / o con un poco de conectividad de red) que la solicitud se cuelgue y espere para siempre.

El siguiente código (que también usa Apache IO Commons) tiene esto en cuenta y espera un máximo de. 5 segundos hasta que falle:

 public static byte[] downloadFile(URL url) { try { URLConnection conn = url.openConnection(); conn.setConnectTimeout(5000); conn.setReadTimeout(5000); conn.connect(); ByteArrayOutputStream baos = new ByteArrayOutputStream(); IOUtils.copy(conn.getInputStream(), baos); return baos.toByteArray(); } catch (IOException e) { // Log error and return null, some default or throw a runtime exception } } 

La longitud del contenido es solo un encabezado HTTP. No puedes confiar en eso. Simplemente lee todo lo que puedas de la transmisión.

Disponible es definitivamente incorrecto. Es solo la cantidad de bytes que se pueden leer sin bloquear.

Otro problema es su manejo de recursos. Cerrar el flujo tiene que suceder en cualquier caso. try / catch / finally hará eso.