datahandler bytearraydatasource array java inputstream outputstream

java - bytearraydatasource - ¿Cómo convertir un InputStream a un DataHandler?



datahandler java (7)

Aquí hay una respuesta para trabajar específicamente con el objeto Spring Boot org.springframework.core.io.Resource que es, creo, cómo muchos de nosotros estamos llegando aquí. Tenga en cuenta que es posible que deba modificar el tipo de contenido en el código a continuación, ya que estoy insertando un archivo png en un correo electrónico con formato html.

Nota: Como han mencionado otros, simplemente adjuntar un InputStream no es suficiente, ya que se usa varias veces, solo el mapeo a través de Resource.getInputStream () hace el truco.

public class SpringResourceDataSource implements DataSource { private Resource resource; public SpringResourceDataSource(Resource resource) { this.resource = resource; } @Override public InputStream getInputStream() throws IOException { return resource.getInputStream(); } @Override public OutputStream getOutputStream() throws IOException { throw new UnsupportedOperationException("Not implemented"); } @Override public String getContentType() { return "image/png"; } @Override public String getName() { return "SpringResourceDataSource"; } }

El uso de la clase se ve así:

PathMatchingResourcePatternResolver pathMatchingResourcePatternResolver = new PathMatchingResourcePatternResolver(); Resource logoImage = pathMatchingResourcePatternResolver.getResource("/static/images/logo.png"); MimeBodyPart logoBodyPart = new MimeBodyPart(); DataSource logoFileDataSource = new SpringResourceDataSource(logoImage); logoBodyPart.setDataHandler(new DataHandler(logoFileDataSource));

Estoy trabajando en una aplicación web java en la que los archivos se almacenarán en una base de datos. Originalmente, recuperamos archivos que ya se encontraban en la base de datos simplemente llamando a getBytes en nuestro conjunto de resultados:

byte[] bytes = resultSet.getBytes(1); ...

Esta matriz de bytes se convirtió luego en un DataHandler usando el constructor obvio:

dataHandler=new DataHandler(bytes,"application/octet-stream");

Esto funcionó muy bien hasta que comenzamos a tratar de almacenar y recuperar archivos más grandes. Volcar todo el contenido del archivo en una matriz de bytes y luego construir un DataHandler partir de eso simplemente requiere demasiada memoria.

Mi idea inmediata es recuperar un flujo de datos en la base de datos con getBinaryStream y de alguna manera convertir ese InputStream en un DataHandler de una manera eficiente en memoria. Desafortunadamente, no parece que haya una forma directa de convertir un InputStream en un DataHandler . Otra idea con la que he estado jugando es leer fragmentos de datos de InputStream y escribirlos en OutputStream del DataHandler . Pero ... no puedo encontrar una manera de crear un DataHandler "vacío" que devuelva un OutputStream no sea nulo cuando llamo a getOutputStream ...

¿Alguien ha hecho esto? Apreciaría cualquier ayuda que me pueda dar o dirija en la dirección correcta.


El código (bugs_) no funciona para mí. Uso DataSource para crear archivos adjuntos al correo electrónico (de objetos que tienen inputStream y nombre ) y se perdió el contenido de los archivos adjuntos. Parece que Stefan tiene razón y que se debe devolver el nuevo inputStream cada vez. Al menos en mi caso específico. La siguiente implementación trata con el problema:

public class InputStreamDataSource implements DataSource { ByteArrayOutputStream buffer = new ByteArrayOutputStream(); private final String name; public InputStreamDataSource(InputStream inputStream, String name) { this.name = name; try { int nRead; byte[] data = new byte[16384]; while ((nRead = inputStream.read(data, 0, data.length)) != -1) { buffer.write(data, 0, nRead); } buffer.flush(); inputStream.close(); } catch (IOException e) { e.printStackTrace(); } } @Override public String getContentType() { return new MimetypesFileTypeMap().getContentType(name); } @Override public InputStream getInputStream() throws IOException { return new ByteArrayInputStream(buffer.toByteArray()); } @Override public String getName() { return name; } @Override public OutputStream getOutputStream() throws IOException { throw new IOException("Read-only data"); } }


Me encontré con la situación, cuando InputStream solicitó a DataSource dos veces: usar Logging Handler junto con la función MTOM. Con esta solución de transmisión proxy mi implementación funciona bien:

import org.apache.commons.io.input.CloseShieldInputStream; import javax.activation.DataHandler; import javax.activation.DataSource; ... private static class InputStreamDataSource implements DataSource { private InputStream inputStream; @Override public InputStream getInputStream() throws IOException { return new CloseShieldInputStream(inputStream); } @Override public OutputStream getOutputStream() throws IOException { throw new UnsupportedOperationException("Not implemented"); } @Override public String getContentType() { return "application/octet-stream"; } @Override public String getName() { return ""; } }


Mi enfoque sería escribir una clase personalizada implementando DataSource que envuelva su InputStream . Luego crea el DataHandler dándole el DataSource creado.


También me encontré con este problema. Si sus datos de origen son un byte[] Axis ya tiene una clase que envuelve el InputStream y crea un objeto DataHandler. Aquí está el código

//this constructor takes byte[] as input ByteArrayDataSource rawData= new ByteArrayDataSource(resultSet.getBytes(1)); DataHandler data= new DataHandler(rawData); yourObject.setData(data);

Importaciones relacionadas

import javax.activation.DataHandler; import org.apache.axiom.attachments.ByteArrayDataSource;

¡Espero eso ayude!



Una implementación de la respuesta de "Kathy Van Stone":

Al principio, cree la clase auxiliar, que crea DataSource de InputStream:

public class InputStreamDataSource implements DataSource { private InputStream inputStream; public InputStreamDataSource(InputStream inputStream) { this.inputStream = inputStream; } @Override public InputStream getInputStream() throws IOException { return inputStream; } @Override public OutputStream getOutputStream() throws IOException { throw new UnsupportedOperationException("Not implemented"); } @Override public String getContentType() { return "*/*"; } @Override public String getName() { return "InputStreamDataSource"; } }

Y luego puedes crear DataHandler desde InputStream:

DataHandler dataHandler = new DataHandler(new InputStreamDataSource(inputStream))

importaciones :

import javax.activation.DataSource; import java.io.OutputStream; import java.io.InputStream;