2017-06-06 1 views
0

J'ai un service REST sur la connexion https qui accepte le téléchargement de fichiers comme multipart (par exemple les métadonnées du fichier et fichier lui-même)service REST - multipart Post (JSON et fichier) en tant que flux sur https en utilisant Jersey

Comment puis-je utilisez Jersey (pour websphere) ou HttpClient pour appeler le service REST et envoyer le fichier en multipart. Je veux envoyer le fichier en tant que plusieurs flux de différentes tailles, car nous pouvons avoir un fichier de plus de 1 Go. En outre, le service REST utilise l'authentification Windows NT pour l'autorisation et est sur https.

Quelqu'un peut-il donner des exemples de comment je peux y parvenir? J'ai utilisé multiClient httpClient. L'envoyer en flux ne fonctionne pas. Ci-dessous est mon code utilisant httpClient 4.5.2

==================================

InputStream stream = new FileInputStream("test.doc"); 

MultipartEntityBuilder entityBuilder = MultipartEntityBuilder.create(); 
entityBuilder.setStrictMode(); 

InputStreamBody streamBody = new InputStreamBody(stream, docHandler.getFilename()); 

FormBodyPart filePart = FormBodyPartBuilder.create() 
       .setName("Binary") 
       .addField(Constants.RETRIEVAL_NAME_FIELD, "test.doc")    
       .addField("Content-Type",docHandler.getContentType()) 
       .setBody(streamBody) 
       .build(); 
entityBuilder.addPart(filePart); 

HttpPost httpPostRequest = new HttpPost(); 
httpPostRequest.setEntity(entityBuilder.build()); 

httpClient.execute(httpPostRequest); 

==================================== Mais quand j'exécute ce code, Je reçois l'erreur suivante

org.apache.http.client.NonRepeatableRequestException: Impossible réessayer la demande avec une entité de demande non répétable

Toute idée pourquoi je reçois cette erreur. Si je convertis stream en tableau byteArray et utilise ByteArrayBody à la place, alors cela fonctionne bien mais j'ai remarqué dans Fiddler que trois appels de requête sont faits au serveur et dans chaque appel le contenu entier du fichier est copié. Donc, si mon fichier est de 1 Go, tout le contenu sera envoyé au serveur trois fois. Tout d'abord, comment puis-je obtenir l'envoi de gros fichiers en morceaux ou en plusieurs flux de sorte que le fichier entier ne soit pas envoyé en un seul appel. Deuxièmement, est-il un moyen d'éviter d'avoir 3 appels au serveur pour l'authentification NTLM?

Des pointeurs?

À la votre!

+0

Copie possible de [Jersey 2 Multipart upload Client] (https://stackoverflow.com/questions/24637038/jersey-2-multipart-upload-client) – andih

+0

Salut andih, ce lien utilise une connexion HTTP simple et non avoir une authentification. Dans mon cas, le service RESTful est sur https et utilise le mécanisme d'authentification NTLM. Y at-il un bon exemple pour télécharger le fichier en tant que flux (je suis inputtream) via le service REST sur https en utilisant le mécanisme d'authentification NTLM? En outre, nous avons websphere où l'application client Java sera en cours d'exécution. Le serveur est implémenté dans .Net. – sab123

+0

Le client HTTP Apache prend en charge http et https. Dans la plupart des cas, vous n'avez même pas besoin de modifier votre code. L'authentification NTLM est quelque chose "au-dessus" de http (s). La version des clients Http Apache> 4.1 (4.2.3) prend en charge [NTLM] (https://hc.apache.org/httpcomponents-client-ga/ntlm.html). Il semble que vous demandiez différentes choses au sein d'une même question. Comment le téléchargement de bloc est un doublon. Le schéma d'authentification NTLM est décrit [ici] (https://www.innovation.ch/personal/ronald/ntlm.html). Si vous pouvez éviter les trois appels. La réponse est non. Vous devriez poser des questions plus spécifiques. – andih

Répondre

0

L'exception se produit car InputStreamBody n'est pas répétable (en particulier pour les flux importants). Un général InputStream peut être lu à partir d'une seule fois.

FileBody est répétable, car un fichier peut être lu plusieurs fois.

Une raison pour les lectures répétables peut être l'autorisation (NTLM) (n'a pas vérifié cela).

Vous pouvez éviter cela en faisant les deux premières étapes d'autorisation NTML avant que la demande réelle et le réglage/envoyer l'en-tête Authorization: NTLM <base64-encoded type-3-message>, mais cela ne résout pas le problème, car le réseau peut ne pas être suffisamment fiable et vous devez réessayer en tous cas.

Vous avez essentiellement deux options:

  1. utilisation ContentBody répétables implémentations seulement comme FileBody ou propre répétables exemple ContentBody.
  2. Assurez-vous que la requête n'a pas besoin d'être réessayée.

S'il vous plaît noter ce dernier est pas toujours possible.Comme mentionné précédemment, les tentatives de demande dues à des échecs d'authentification peuvent être évitées, mais celles dues aux erreurs d'E/S ne peuvent pas l'être.

+0

cela signifie-t-il que nous ne pouvons pas publier un document en tant que flux en utilisant le service REST avec l'authentification NTLM ou est-ce la limitation de httpClient? Y a-t-il une autre API client REST qui peut le faciliter comme Jersey ou autre? Si l'enregistrement en tant que flux n'est pas possible car il est intrinsèquement non répétable, alors où InputStreamBody sera-t-il utilisé comme un multiple en utilisant httpClient? – sab123

+0

Cela n'a rien à voir avec les limitations de NTLM ou du client. Le client supporte la publication de flux dès qu'ils sont reproductibles comme le 'FileBody' qui est également envoyé en flux. La différence entre 'InputStream' et' File' est qu'avec un 'File' vous pouvez implémenter quelque chose comme un accès aléatoire, c'est-à-dire sauter à un point donné alors qu'avec le' InputStreams' général vous ne pouvez pas. Vous pouvez également surmonter les problèmes d'autorisation (non spécifiques à NTLM) en préautorisant/autorisez la demande, mais vous devez toujours gérer les erreurs d'E/S. C'est juste si vous voulez l'utiliser de cette façon, vous devez faire un peu de travail. – andih

+0

remercie Andih pour la réponse. Je pensais que filebody chargeait tout le fichier en mémoire et l'envoyait dans le cadre de la requête. Si le fichier utilise le flux interne, alors cela devrait être bon. Nous avons un service de téléchargement équivalent qui est sur SOAP (authentification de base) pour télécharger le fichier et il y a envoi d'inputStream avec MTOM activé et cela fonctionne. Dans le scénario actuel, nous avons REST et essayions de déterminer si inputStream pouvait être envoyé à REST de la même manière que nous le faisons dans SOAP sans créer de fichier temporaire. – sab123