Question

J'ai écrit une petite application qui permettra aux gens de télécharger & amp; télécharger des fichiers pour moi. J'ai ajouté un service Web à cette application pour fournir la fonctionnalité de téléchargement / téléchargement de cette manière, mais je ne suis pas certain de la capacité de mon implémentation à gérer des fichiers volumineux.

Pour le moment, les définitions du fichier upload & amp; Les méthodes de téléchargement ressemblent à ceci (écrit avec 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;

Le fichier est donc téléchargé et téléchargé comme un tableau d'octets. Mais si j’ai un fichier d’une taille stupide (par exemple, 1 Go), cela va sûrement essayer de mettre toutes ces informations en mémoire et de bloquer le service.

Donc, ma question est la suivante: est-il possible de renvoyer une sorte de flux à la place? J'imagine que cela ne va pas être très indépendant du système d'exploitation. Bien que je connaisse la théorie des services Web, il me faut encore un peu d’informations pratiques.

Merci pour toute entrée, Lee

Était-ce utile?

La solution

Stephen Denne a une implémentation Metro qui répond à vos besoins. Ma réponse est fournie ci-dessous après une brève explication de la raison pour laquelle c'est le cas.

La plupart des implémentations de service Web construites à l'aide de HTTP en tant que protocole de message sont conformes à REST, en ce sens qu'elles n'autorisent que de simples modèles d'envoi-réception et rien de plus. Cela améliore considérablement l’interopérabilité, car toutes les plates-formes peuvent comprendre cette architecture simple (par exemple, un service Web Java communiquant avec un service Web .NET).

Si vous souhaitez conserver cette information, vous pouvez fournir une segmentation.

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

Cela nécessiterait un jeu de jambes dans les cas où les morceaux ne sont pas placés dans le bon ordre (ou vous pouvez simplement exiger que les morceaux arrivent dans le bon ordre), mais ce serait probablement assez facile à mettre en œuvre.

Autres conseils

Oui, c'est possible avec Metro. Voir l'exemple grandes pièces jointes , qui ressemble à ce que vous voulez. .

  

JAX-WS RI prend en charge l'envoi et la réception de pièces jointes volumineuses en mode continu.

     
      
  • Utilisez MTOM et DataHandler dans le modèle de programmation.
  •   
  • Convertissez DataHandler sur StreamingDataHandler et utilisez ses méthodes.
  •   
  • Assurez-vous d'appeler StreamingDataHandler.close () et fermez également le flux StreamingDataHandler.readOnce ().
  •   
  • Activer la segmentation HTTP côté client.
  •   

Lorsque vous utilisez un service Web normalisé, l'expéditeur et le destinataire s'appuient sur l'intégrité des données XML envoyées de l'un à l'autre. Cela signifie qu'une demande de service Web et une réponse uniquement sont terminées lorsque la dernière balise a été envoyée. Sachant cela, un service Web ne peut pas être traité comme un flux.

Ceci est logique car les services Web standardisés reposent sur le protocole http. Celui-ci est "sans état", dira que cela fonctionne comme "une connexion ouverte ... envoie une demande ... reçoit des données ... demande proche". La connexion sera fermée à la fin, de toute façon. Donc, quelque chose comme le streaming n'est pas destiné à être utilisé ici. Ou il couche au-dessus de http (comme les services Web).

Désolé, mais autant que je sache, il n’ya aucune possibilité de diffusion en continu dans les services Web. Pire encore: selon l'implémentation / la configuration d'un service Web, octet [] - les données peuvent être traduites en Base64 et non en balise CDATA et la demande peut devenir encore plus lourde.

P.S .: Oui, comme d'autres l'ont écrit, "chuinking" est possible. Mais ce n’est pas du streaming en tant que tel ;-) - de toute façon, cela peut vous aider.

Je déteste le dire à ceux d'entre vous qui pensent qu'un service Web en streaming n'est pas possible, mais en réalité, toutes les demandes http sont basées sur des flux. Chaque navigateur effectuant une opération GET sur un site Web est basé sur un flux. Chaque appel à un service Web est basé sur un flux. Oui tout. Nous ne le remarquons pas au niveau où nous mettons en œuvre des services ou des pages, car les niveaux inférieurs de l’architecture traitent de cela pour vous - mais cela se fait.

Avez-vous déjà remarqué, dans un navigateur, que la récupération d'une page peut parfois prendre un certain temps - le navigateur n'arrête pas de montrer le sablier? En effet, le navigateur attend un flux.

Les flux sont la raison pour laquelle les mimes / types doivent être envoyés avant les données réelles - il ne s'agit que d'un flux d'octets destiné au navigateur. Il ne serait pas en mesure d'identifier une photo si vous ne lui disiez pas ce qu'il était en premier. . C’est aussi pourquoi vous devez passer la taille d’un fichier binaire avant de l’envoyer - le navigateur ne pourra pas dire où l’image s’arrête et la page se relance.

Il s’agit uniquement d’un flux d’octets transmis au client. Si vous voulez le prouver par vous-même, il vous suffit de vous procurer le flux de sortie à tout moment du traitement d'une requête et de le fermer (). Vous allez tout faire sauter. Le navigateur cessera immédiatement d’afficher le sablier et affichera un message «impossible de trouver». ou "réinitialisation de la connexion sur le serveur". ou un autre tel message.

Le fait que beaucoup de gens ne sachent pas que tout cela est basé sur le flux montre à quel point le contenu a été superposé. Certains diraient trop de choses - j'en fais partie.

Bonne chance et bon développement - relâchez les épaules!

Pour WCF, je pense qu'il est possible de définir un membre sur un message en tant que flux et de définir la liaison de manière appropriée - j'ai déjà vu ce travail avec wcf parler au service Web Java.

Vous devez définir le paramètre transferMode = " StreamedResponse " dans la configuration httpTransport et utilisez mtomMessageEncoding (vous devez utiliser une section de liaison personnalisée dans la configuration).

Je pense qu'une des limites est que vous ne pouvez avoir qu'un seul membre du corps du message si vous souhaitez diffuser (ce qui a du sens).

Apache CXF prend en charge l'envoi et la réception de flux.

Une façon de le faire est d’ajouter une méthode uploadFileChunk (byte [] chunkData, int size, int offset, int totalSize) (ou quelque chose comme ça) qui télécharge des parties du fichier les serveurs l’écrivent sur le disque.

N'oubliez pas qu'une demande de service Web se résume à un seul HTTP POST.

Si vous consultez le résultat d'un fichier .ASMX dans .NET, il vous montre exactement à quoi ressembleront la demande et la réponse POST.

Chunking, comme mentionné par @Guvante, sera la chose la plus proche de ce que vous voulez.

Je suppose que vous pouvez implémenter votre propre code de client Web pour gérer le protocole TCP / IP et diffuser des éléments dans votre application, mais cela serait pour le moins complexe.

Je pense que l'utilisation d'une simple servlet pour cette tâche serait une approche beaucoup plus simple. , ou y a-t-il une raison pour laquelle vous ne pouvez pas utiliser une servlet?

Par exemple, vous pouvez utiliser la bibliothèque ouverte Commons .

La bibliothèque RMIIO pour Java permet de gérer un flux RemoteInputStream via RMI - nous n'avions besoin que de RMI, Cependant, vous devriez être capable d’adapter le code à d’autres types de RMI. Cela peut vous aider, surtout si vous pouvez avoir une petite application côté utilisateur. La bibliothèque a été développée dans le seul but de pouvoir limiter la taille des données transmises au serveur afin d'éviter exactement le type de situation que vous décrivez - une attaque DOS en remplissant votre mémoire vive ou votre disque.

Avec la bibliothèque RMIIO, le serveur doit décider du volume de données qu’il souhaite extraire. Dans le cas de HTTP PUT et de POST, le client doit prendre cette décision, y compris la vitesse à laquelle il pousse.

Oui, un service Web peut diffuser en continu. J'ai créé un service Web à l'aide d'Apache Axis2 et de MTOM afin de prendre en charge le rendu de documents PDF à partir de XML. Comme les fichiers résultants pouvaient être volumineux, la diffusion en continu était importante car nous ne voulions pas tout garder en mémoire. Consultez la documentation d'Oracle sur la streaming de pièces jointes SOAP.

Vous pouvez également le faire vous-même et tomcat créera les en-têtes Chunked. Ceci est un exemple de fonction de contrôleur de ressort qui diffuse.

 @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();

    }

Il n’est pas si difficile de "manipuler le protocole TCP / IP et de diffuser des éléments dans votre application". Essayez ceci ...

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

Et c'est tout ce qu'il y a à faire. Dans le code ci-dessus, vous avez répondu à une requête HTTP GET envoyée par un navigateur et renvoyé à ce navigateur le texte "Hello World!".

N'oubliez pas que "Hello World!" n’est pas valide en HTML, vous pouvez donc vous retrouver avec une erreur sur le navigateur, mais c’est tout ce que vous avez à faire.

Bonne chance dans votre développement!

Rodney

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top