Téléchargement de fichier avec un autre object dans le service Web de restauration de Jersey

Je souhaite créer des informations sur les employés dans le système en téléchargeant une image avec les données des employés. Je suis capable de le faire avec différents appels de repos avec maillot. Mais je veux réaliser un appel de repos. Je fournis ci-dessous la structure. Aidez-moi s’il vous plaît comment faire à cet égard.

@POST @Path("/upload2") @Consumes({MediaType.MULTIPART_FORM_DATA,MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON}) public Response uploadFileWithData( @FormDataParam("file") InputStream fileInputStream, @FormDataParam("file") FormDataContentDisposition contentDispositionHeader, Employee emp) { //..... business login } 

Chaque fois que j’essaie de le faire, j’obtiens une erreur dans Chrome Postman. La structure simple de mon employé json est donnée ci-dessous.

 { "Name": "John", "Age": 23, "Email": "[email protected]", "Adrs": { "DoorNo": "12-A", "Street": "Street-11", "City": "Bangalore", "Country": "Karnataka" } } 

Cependant, je peux le faire en effectuant deux appels différents, mais je veux réaliser en un seul appel pour que je puisse recevoir le fichier ainsi que les données réelles de l’employé.

Demandez-vous de vous aider à cet égard.

Vous ne pouvez pas avoir deux Content-Type s (eh bien, techniquement c’est ce que nous faisons ci-dessous, mais ils sont séparés avec chaque partie du multipart, mais le type principal est multipart). C’est essentiellement ce que vous attendez avec votre méthode. Vous attendez mutlipart et json ensemble comme type de média principal. Les données d’ Employee doivent faire partie du multipart. Vous pouvez donc append un @FormDataParam("emp") pour l’ Employee .

 @FormDataParam("emp") Employee emp) { ... 

Voici la classe que j’ai utilisée pour les tests

 @Path("/multipart") public class MultipartResource { @POST @Path("/upload2") @Consumes({MediaType.MULTIPART_FORM_DATA}) public Response uploadFileWithData( @FormDataParam("file") InputStream fileInputStream, @FormDataParam("file") FormDataContentDisposition cdh, @FormDataParam("emp") Employee emp) throws Exception{ Image img = ImageIO.read(fileInputStream); JOptionPane.showMessageDialog(null, new JLabel(new ImageIcon(img))); System.out.println(cdh.getName()); System.out.println(emp); return Response.ok("Cool Tools!").build(); } } 

D’abord, je viens de tester avec l’API client pour m’assurer qu’il fonctionne

 @Test public void testGetIt() throws Exception { final Client client = ClientBuilder.newBuilder() .register(MultiPartFeature.class) .build(); WebTarget t = client.target(Main.BASE_URI).path("multipart").path("upload2"); FileDataBodyPart filePart = new FileDataBodyPart("file", new File("stackoverflow.png")); // UPDATE: just tested again, and the below code is not needed. // It's redundant. Using the FileDataBodyPart already sets the // Content-Disposition information filePart.setContentDisposition( FormDataContentDisposition.name("file") .fileName("stackoverflow.png").build()); Ssortingng empPartJson = "{\n" + " \"id\": 1234,\n" + " \"name\": \"Peeskillet\"\n" + "}\n" + ""; MultiPart multipartEntity = new FormDataMultiPart() .field("emp", empPartJson, MediaType.APPLICATION_JSON_TYPE) .bodyPart(filePart); Response response = t.request().post( Entity.entity(multipartEntity, multipartEntity.getMediaType())); System.out.println(response.getStatus()); System.out.println(response.readEntity(Ssortingng.class)); response.close(); } 

Je viens de créer une simple classe Employee avec un champ id et name pour le test. Cela fonctionne parfaitement bien. Il affiche l’image, imprime la disposition du contenu et imprime l’object Employee .

Je ne suis pas trop familier avec Postman, j’ai donc sauvegardé ce test pour la dernière fois 🙂

entrer la description de l'image ici

Cela semble fonctionner correctement, comme vous pouvez voir la réponse "Cool Tools" . Mais si nous regardons les données imprimées des Employee , nous verrons que c’est nul. Ce qui est bizarre car avec l’API client, cela fonctionnait bien.

Si nous regardons la fenêtre de prévisualisation, nous verrons le problème

entrer la description de l'image ici

Il n’y a pas d’en Content-Type tête Content-Type pour la partie du corps emp . Vous pouvez voir dans l’API du client que je l’ai explicitement définie

 MultiPart multipartEntity = new FormDataMultiPart() .field("emp", empPartJson, MediaType.APPLICATION_JSON_TYPE) .bodyPart(filePart); 

Donc, je suppose que ce n’est vraiment qu’une partie d’une réponse complète. Comme je l’ai dit, je ne connais pas bien Postman. Je ne sais donc pas comment définir Content-Type s pour des parties du corps individuelles. L’ image/png pour l’image a été automatiquement définie pour moi pour la partie d’image (je suppose que c’était juste déterminé par l’extension de fichier). Si vous pouvez le comprendre, le problème doit être résolu. S’il vous plaît, si vous découvrez comment faire cela, postez-le comme une réponse.


Et juste pour être complet …

  • Voir ici pour plus d’informations sur MultiPart with Jersey .

Configurations de base:

Dépendance:

  org.glassfish.jersey.media jersey-media-multipart ${jersey2.version}  

Configuration du client:

 final Client client = ClientBuilder.newBuilder() .register(MultiPartFeature.class) .build(); 

Configuration du serveur:

 // Create JAX-RS application. final Application application = new ResourceConfig() .packages("org.glassfish.jersey.examples.multipart") .register(MultiPartFeature.class); 

METTRE À JOUR

Comme vous pouvez le voir sur le client Postman, certains clients ne peuvent pas définir le type de contenu de chaque composant, y compris le navigateur, en ce qui concerne ses capacités par défaut lors de l’utilisation de FormData (js).

Nous ne pouvons pas nous attendre à ce que le client trouve ce moyen, alors ce que nous pouvons faire, c’est lors de la réception des données, définir explicitement le type de contenu avant la désérialisation. Par exemple

 @POST @Path("upload2") @Consumes(MediaType.MULTIPART_FORM_DATA) public Response uploadFileAndJSON(@FormDataParam("emp") FormDataBodyPart jsonPart, @FormDataParam("file") FormDataBodyPart bodyPart) { jsonPart.setMediaType(MediaType.APPLICATION_JSON_TYPE); Employee emp = jsonPart.getValueAs(Employee.class); } 

C’est un petit travail supplémentaire pour obtenir le POJO, mais c’est une meilleure solution que de forcer le client à essayer de trouver sa propre solution.

Vous pouvez accéder au fichier image et aux données d’un formulaire en utilisant MULTIPART FORM DATA en utilisant le code ci-dessous.

 @POST @Path("/UpdateProfile") @Consumes(value={MediaType.APPLICATION_JSON,MediaType.MULTIPART_FORM_DATA}) @Produces(value={MediaType.APPLICATION_JSON,MediaType.APPLICATION_XML}) public Response updateProfile( @FormDataParam("file") InputStream fileInputStream, @FormDataParam("file") FormDataContentDisposition contentDispositionHeader, @FormDataParam("ProfileInfo") Ssortingng ProfileInfo, @FormDataParam("registrationId") Ssortingng registrationId) { Ssortingng filePath= "/filepath/"+contentDispositionHeader.getFileName(); OutputStream outputStream = null; try { int read = 0; byte[] bytes = new byte[1024]; outputStream = new FileOutputStream(new File(filePath)); while ((read = fileInputStream.read(bytes)) != -1) { outputStream.write(bytes, 0, read); } outputStream.flush(); outputStream.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { if (outputStream != null) { try { outputStream.close(); } catch(Exception ex) {} } } } 

Votre applicationConfig doit enregistrer la classe MultiPartFeature.class à partir de la page glassfish.jersey.media .. afin de permettre le téléchargement du fichier

 @javax.ws.rs.ApplicationPath(ResourcePath.API_ROOT) public class ApplicationConfig extends ResourceConfig { public ApplicationConfig() { //register the necessary headers files needed from client register(CORSConfigurationFilter.class); //The jackson feature and provider is used for object serialization //between client and server objects in to a json register(JacksonFeature.class); register(JacksonProvider.class); //Glassfish multipart file uploader feature register(MultiPartFeature.class); //inject and registered all resources class using the package //not to be tempered with packages("com.flexisaf.safhrms.client.resources"); register(RESTRequestFilter.class); } 

Je veux append un commentaire sur peeskillet, mais je n’ai pas 50 points de réputation, ce qui ajoute une réponse:

Lorsque j’ai essayé la solution @peeskillet avec le client Jersey 2.21.1, il y avait 400 erreurs. Cela a fonctionné quand j’ai ajouté en suivant dans mon code client:

  MediaType contentType = MediaType.MULTIPART_FORM_DATA_TYPE; contentType = Boundary.addBoundary(contentType); Response response = t.request().post( Entity.entity(multipartEntity, contentType)); 

au lieu de MediaType.MULTIPART_FORM_DATA codé en dur dans l’appel de post-demande.

J’ai utilisé l’exemple de téléchargement de fichier,

http://www.mkyong.com/webservices/jax-rs/file-upload-example-in-jersey/

dans ma classe de ressources, j’ai ci-dessous la méthode

 @POST @Path("/upload") @Consumes(MediaType.MULTIPART_FORM_DATA) public Response attachupload(@FormDataParam("file") byte[] is, @FormDataParam("file") FormDataContentDisposition fileDetail, @FormDataParam("fileName") Ssortingng flename){ attachService.saveAttachment(flename,is); } 

dans mon attachService.java j’ai ci-dessous la méthode

  public void saveAttachment(Ssortingng flename, byte[] is) { // TODO Auto-generated method stub attachmentDao.saveAttachment(flename,is); } 

à Dao j’ai

 attach.setData(is); attach.setFileName(flename); 

dans ma cartographie HBM est comme

    

Cela fonctionne pour tous les types de fichiers tels que .PDF, .TXT, .PNG etc.,

Définissez le “Content-Type: multipart / form-data” du côté client et cela devrait faire le travail