¿Puede un servicio web devolver una transmisión?


He estado escribiendo una pequeña aplicación que permitirá a la gente subir y descargar archivos para mí. He añadido un servicio web a esta aplicación para proporcionar la funcionalidad de carga/descarga de esa manera, pero no estoy muy seguro de lo bien que mi implementación va a hacer frente a los archivos de gran tamaño.

Por el momento las definiciones de los métodos de carga y descarga se ven así (escritas usando Apache CXF):

boolean uploadFile(@WebParam(name = "username") String username,
    @WebParam(name = "password") String password,
    @WebParam(name = "filename") String filename,
    @WebParam(name = "fileContents") byte[] fileContents)
    throws UploadException, LoginException;

byte[] downloadFile(@WebParam(name = "username") String username,
    @WebParam(name = "password") String password,
    @WebParam(name = "filename") String filename) throws DownloadException,
    LoginException;

Así que el archivo se carga y descarga como una matriz de bytes. Pero si tengo un archivo de algún tamaño estúpido (por ejemplo, 1GB) seguramente esto intentará poner toda esa información en la memoria y bloqueará mi servicio.

Así que mi pregunta es - ¿es posible devolver algún tipo de corriente en su lugar? Me imagino que esto no va a ser terriblemente independiente. Aunque conozco la teoría detrás de los servicios web, el lado práctico es algo sobre lo que todavía necesito recoger un poco de información.

Saludos para cualquier entrada, Lee

Author: David, 2008-09-25

12 answers

Stephen Denne tiene una implementación de Metro que satisface sus requisitos. Mi respuesta se proporciona a continuación después de una breve explicación de por qué es el caso.

La mayoría de las implementaciones de Servicios Web que se construyen usando HTTP como protocolo de mensajes son compatibles con REST, ya que solo permiten patrones simples de envío-recepción y nada más. Esto mejora enormemente la interoperabilidad, ya que todas las diversas plataformas pueden entender esta arquitectura simple (por ejemplo, una web Java servicio que habla con un servicio web. NET).

Si desea mantener esto, podría proporcionar chunking.

boolean uploadFile(String username, String password, String fileName, int currentChunk, int totalChunks, byte[] chunk);

Esto requeriría un poco de juego de pies en los casos en los que no obtiene los trozos en el orden correcto (O simplemente puede requerir que los trozos vienen en el orden correcto), pero probablemente sería bastante fácil de implementar.

 6
Author: Guvante,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:09:00

Sí, es posible con Metro. Vea el ejemplo Archivos adjuntos grandes, que parece que hace lo que desea.

JAX-WS RI proporciona soporte para enviar y recibir archivos adjuntos de gran tamaño en streaming.

  • Utilice MTOM y DataHandler en el modelo de programación.
  • Envía el DataHandler a StreamingDataHandler y usa sus métodos.
  • Asegúrese de llamar a StreamingDataHandler.cerrar () y también cerrar el StreamingDataHandler.readOnce() flujo.
  • Habilita el chunking HTTP en el lado del cliente.
 14
Author: Stephen Denne,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-04-03 07:55:55

Cuando se utiliza un servicio web estandarizado, el remitente y el receptor confían en la integridad de los datos XML enviados de uno a otro. Esto significa que una solicitud de servicio web y una respuesta solo se completan cuando se envió la última etiqueta. Teniendo esto en cuenta, un servicio web no puede ser tratado como una transmisión.

Esto es lógico porque los servicios web estandarizados dependen del protocolo http. Que uno es "sin estado", dirá que funciona como " conexión abierta ... enviar solicitud ... recibir datos ... close request"(en inglés). La conexión se cerrará al final, de todos modos. Así que algo como streaming no está destinado a ser utilizado aquí. O capas por encima de http (como los servicios web).

Lo siento, pero por lo que puedo ver no hay posibilidad de streaming en los servicios web. Peor aún: dependiendo de la implementación / configuración de un servicio web, los bytes[] - data pueden ser traducidos a Base64 y no a la etiqueta CDATA y la solicitud puede ser aún más hinchada.

P.d.: Sí, como otros escribieron, "chuinking" es posible. Pero esto no es streaming como tal; -) - de todos modos, puede ayudarle.

 3
Author: Georgi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-25 11:05:41

Odio decirselo a aquellos de ustedes que piensan que un servicio web de streaming no es posible, pero en realidad, todas las solicitudes http se basan en stream. Cada navegador que hace un LLEGAR a un sitio web se basa en flujo. Cada llamada a un servicio web está basada en stream. Sí, todos. No nos damos cuenta de esto en el nivel donde estamos implementando servicios o páginas porque los niveles más bajos de la arquitectura se ocupan de esto para usted, pero se está haciendo.

¿Alguna vez has notado en un navegador que a veces se puede tomar un tiempo para obtener una página-el navegador solo mantiene arranque de distancia mostrando el reloj de arena? Esto se debe a que el navegador está esperando en una transmisión.

Los flujos son la razón por la que los tipos/mime deben enviarse antes que los datos reales: todo es solo un flujo de bytes al navegador, no podría identificar una foto si no le dijera lo que fue primero. También es por eso que tienes que pasar el tamaño de un binario antes de enviar-el navegador no será capaz de decir dónde se detiene la imagen y la página recoge de nuevo.

Todo es solo un flujo de bytes para el cliente. Si quieres probar esto por ti mismo, simplemente consigue un control del flujo de salida en cualquier punto del procesamiento de una solicitud y ciérralo (). Volarás todo. El navegador dejará de mostrar inmediatamente el reloj de arena, y mostrará un "no se puede encontrar" o "restablecimiento de conexión en el servidor" o algún otro mensaje similar.

Que mucha gente no sepa que todo esto está basado en stream muestra cuánto las cosas han sido superpuestas. Algunos dirían demasiadas cosas-yo soy uno de esos.

Buena suerte y feliz desarrollo relajar los hombros!

 1
Author: Rodney Barbati,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-03-14 16:12:02

Para WCF creo que es posible definir un miembro en un mensaje como flujo y establecer el enlace apropiadamente - He visto este trabajo con wcf hablando con Java web service.

Necesita establecer TransferMode="StreamedResponse" en la configuración httpTransport y usar mtomMessageEncoding (necesita usar una sección de enlace personalizada en la configuración).

Creo que una limitación es que solo puede tener un solo miembro del cuerpo del mensaje si desea transmitir (lo que tiene sentido).

 1
Author: Richard,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-12-20 00:04:50

Apache CXF soporta el envío y recepción de flujos.

 1
Author: novice,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-10-16 20:57:31

Una forma de hacerlo es agregar un método uploadFileChunk(byte[] chunkData, int size, int offset, int totalSize) (o algo así) que carga partes del archivo y los servidores lo escriben en el disco.

 0
Author: Pop Catalin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-25 11:02:25

Tenga en cuenta que una solicitud de servicio web básicamente se reduce a una sola publicación HTTP.

Si nos fijamos en la salida de a .Archivo ASMX en. NET, le muestra exactamente cómo se verá la solicitud y la respuesta POST.

Chunking, como se menciona por @Guvante, va a ser lo más parecido a lo que quieres.

Supongo que podría implementar su propio código de cliente web para manejar el TCP / IP y transmitir cosas en su aplicación, pero eso sería complejo decir que el menos.

 0
Author: Eric Z Beard,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-25 11:06:13

Creo que usar un simple servlet para esta tarea sería un enfoque mucho más fácil, o hay alguna razón por la que no puede usar un servlet?

Por ejemplo, podría usar la biblioteca de código abierto Commons.

 0
Author: Drejc,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-25 11:13:38

La biblioteca RMIIO para Java proporciona un RemoteInputStream a través de RMI - solo necesitábamos RMI, aunque debería ser capaz de adaptar el código para que funcione sobre otros tipos de RMI . Esto puede ser de ayuda para usted, especialmente si puede tener una pequeña aplicación en el lado del usuario. La biblioteca se desarrolló con el propósito expreso de poder limitar el tamaño de los datos enviados al servidor para evitar exactamente el tipo de situación que describe, efectivamente un ataque DOS al llenar subir ram o disco.

Con la biblioteca RMIIO, el lado del servidor decide cuántos datos está dispuesto a extraer, donde con HTTP PUT y POSTs, el cliente toma esa decisión, incluida la velocidad a la que envía.

 0
Author: Kyle Burton,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-25 11:59:14

Sí, un servicio web puede hacer streaming. Creé un servicio web utilizando Apache Axis2 y MTOM para soportar la representación de documentos PDF desde XML. Dado que los archivos resultantes podían ser bastante grandes, la transmisión era importante porque no queríamos mantenerlo todo en memoria. Eche un vistazo a la documentación de Oracle sobre transmisión de archivos adjuntos SOAP.

Alternativamente, puede hacerlo usted mismo, y tomcat creará los encabezados fragmentados. Este es un ejemplo de una función de controlador de resorte que flujo.

 @RequestMapping(value = "/stream")
        public void hellostreamer(HttpServletRequest request, HttpServletResponse response) throws CopyStreamException, IOException  
{

            response.setContentType("text/xml");
            OutputStreamWriter writer = new OutputStreamWriter (response.getOutputStream());
            writer.write("this is streaming");
            writer.close();

    }
 0
Author: nont,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-11-11 15:25:17

En realidad no es tan difícil "manejar el TCP/IP y transmitir cosas en su aplicación". Prueba esto...

class MyServlet extends HttpServlet
{
    public void doGet(HttpServletRequest request, HttpServletResponse response)
    {
        response.getOutputStream().println("Hello World!");
    }
}

Y eso es todo lo que hay. En el código anterior, respondió a una solicitud HTTP GET enviada desde un navegador, y devolvió a ese navegador el texto "Hello World!".

Tenga en cuenta que "Hello World!"no es HTML válido, por lo que puede terminar con un error en el navegador, pero eso es todo lo que hay.

Buena suerte en tu desarrollo!

Rodney

 0
Author: Rodney Barbati,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-04-02 19:02:16