Téléchargement de fichiers avec d'autres objets dans le service web restful De Jersey
je veux créer une information d'employé dans le système en téléchargeant une image avec les données d'employé. Je peux le faire avec différents appels de repos en utilisant jersey. Mais je veux réaliser dans un appel reste. Je fournis sous la structure. S'il vous plaît aidez-moi à 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, je reçois une erreur dans Chrome postman. La structure simple de mon employé json est donnée ci-dessous.
{
"Name": "John",
"Age": 23,
"Email": "john@gmail.com",
"Adrs": {
"DoorNo": "12-A",
"Street": "Street-11",
"City": "Bangalore",
"Country": "Karnataka"
}
}
Toutefois, je peux le faire en faisant deux différents d'appel, mais que je veux réaliser dans un appel reste afin que je puisse recevoir le fichier, ainsi que les données réelles de l'employé.
vous demander de l'aide à cet égard.
6 réponses
vous ne pouvez pas en avoir deux Content-Type
s (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 ce que vous attendez de votre méthode. Vous attendez mutlipart!--24-->et JSON ensemble comme le type de média principal. Employee
les données doivent faire partie du multipart. Ainsi, vous pouvez ajouter un @FormDataParam("emp")
pour les Employee
.
@FormDataParam("emp") Employee emp) { ...
Voici la classe que j'ai utilisée pour test
@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();
}
}
tout d'abord je viens de tester avec l'API client pour m'assurer que ça 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());
String 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(String.class));
response.close();
}
je viens de créer un simple Employee
classe id
et name
champ de test. Cela fonctionne parfaitement bien. Il affiche l'image, IMPRIME la disposition du contenu, et imprime le Employee
objet.
Je ne suis pas trop familier avec Postman, donc j'ai gardé ce test pour la fin : -)
Il semble fonctionner bien aussi, comme vous pouvez voir la réponse "Cool Tools"
. Mais si l'on regarde l'imprimé Employee
data, on verra que c'est nul. Ce qui est bizarre car avec l'API client ça a bien fonctionné.
si nous regardons la fenêtre de prévisualisation, nous verrons le problème
Il n'y a pas de Content-Type
en-tête emp
partie du corps. Vous pouvez voir dans l'API client que je l'ai explicitement défini
MultiPart multipartEntity = new FormDataMultiPart()
.field("emp", empPartJson, MediaType.APPLICATION_JSON_TYPE)
.bodyPart(filePart);
alors je suppose que c'est vraiment seulement partie d'une réponse complète. Comme je l'ai dit, Je ne suis pas familier avec Postman donc je ne sais pas comment mettre Content-Type
s pour les différentes parties du corps. image/png
car l'image a été automatiquement définie pour moi pour la partie image (je suppose que c'était juste déterminé par l'extension du fichier). Si vous pouvez comprendre cela, alors le problème devrait être résolu. S'il vous plaît, si vous trouvez comment faire cela, poster une réponse.
Et juste pour exhaustivité...
configurations de base:
Dépendance:
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-multipart</artifactId>
<version>${jersey2.version}</version>
</dependency>
config du Client:
final Client client = ClientBuilder.newBuilder()
.register(MultiPartFeature.class)
.build();
config Server:
// Create JAX-RS application.
final Application application = new ResourceConfig()
.packages("org.glassfish.jersey.examples.multipart")
.register(MultiPartFeature.class);
UPDATE
comme vous pouvez le voir sur le client Postman, certains clients ne sont pas en mesure de définir le type de contenu des différentes parties, ce qui inclut le navigateur, en ce qui concerne c'est la capacité par défaut quand on utilise FormData
(js).
nous ne pouvons pas nous attendre à ce que le client trouve quelque chose autour de cela, donc ce que nous pouvons faire, c'est quand nous recevons les données, définir explicitement le type de contenu avant de désérialiser. 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 peu de 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 les données du formulaire MULTIPART 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") String ProfileInfo,
@FormDataParam("registrationId") String registrationId) {
String 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 MultiPartFeature.classe de glassfish.Jersey.Média.. afin d'activer le téléchargement de 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 ajouter un commentaire sur peeskillet, mais n'ont pas de 50 points de réputation, d'où l'ajout d'une réponse:
quand j'ai essayé @peeskillet solution avec le client De Jersey 2.21.1, il y avait 400 erreur. Il a travaillé quand j'ai ajouté la suite dans mon code:
MediaType contentType = MediaType.MULTIPART_FORM_DATA_TYPE;
contentType = Boundary.addBoundary(contentType);
Response response = t.request().post(
Entity.entity(multipartEntity, contentType));
au lieu de MediaType hardcodé.MULTIPART_FORM_DATA in post request call.
j'ai utilisé de téléchargement de fichiers exemple,
http://www.mkyong.com/webservices/jax-rs/file-upload-example-in-jersey/
dans ma classe de ressource j'ai la méthode ci-dessous
@POST
@Path("/upload")
@Consumes(MediaType.MULTIPART_FORM_DATA)
public Response attachupload(@FormDataParam("file") byte[] is,
@FormDataParam("file") FormDataContentDisposition fileDetail,
@FormDataParam("fileName") String flename){
attachService.saveAttachment(flename,is);
}
dans mon attachService.java j'ai ci-dessous la méthode
public void saveAttachment(String flename, byte[] is) {
// TODO Auto-generated method stub
attachmentDao.saveAttachment(flename,is);
}
dans Dao, j'ai
attach.setData(is);
attach.setFileName(flename);
dans mon HBM de la cartographie est de la forme
<property name="data" type="binary" >
<column name="data" />
</property>
Ce travail pour tous les types de fichiers comme .PDF.,TXT,.PNG etc.,
définir le "type de contenu: multipart / form-data" du côté du client et qui devrait faire le travail