Ich möchte eine Mitarbeiterinformation im System erstellen, indem Sie ein Bild zusammen mit den Mitarbeiterdaten hochladen. Ich kann es mit verschiedenen Ruheanrufen mit Trikot machen. Aber ich möchte in einem Ruhezustand erreichen . Ich gebe unterhalb der Struktur. Bitte helfen Sie mir, wie Sie diesbezüglich tun können.
@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
}
Bei jedem Versuch erhalte ich eine Fehlermeldung in Chrome Postman. Die einfache Struktur meines Employee Json ist unten angegeben.
{
"Name": "John",
"Age": 23,
"Email": "[email protected]",
"Adrs": {
"DoorNo": "12-A",
"Street": "Street-11",
"City": "Bangalore",
"Country": "Karnataka"
}
}
Ich kann es jedoch mit zwei verschiedenen Anrufen tun, aber ich möchte in einem Ruhezustand erreichen, dass ich die Datei sowie die tatsächlichen Daten des Angestellten erhalten kann.
Bitten Sie um Hilfe in dieser Hinsicht.
Sie können nicht zwei Content-Type
Haben (technisch gesehen machen wir das unten, aber sie sind mit jedem Teil des Multiparts getrennt, aber der Haupttyp ist Multipart). Das ist im Grunde, was Sie mit Ihrer Methode erwarten. Sie erwarten, dass als Hauptmedientyp mehrere Teile und json verwendet werden. Die Employee
Daten müssen Teil des Multiparts sein. Sie können also eine @FormDataParam("emp")
für die Employee
hinzufügen.
@FormDataParam("emp") Employee emp) { ...
Hier ist die Klasse, die ich zum Testen verwendet habe
@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();
}
}
Zuerst habe ich nur mit der Client-API getestet, um sicherzustellen, dass es funktioniert
@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
= "{"
+ " \"id\": 1234,"
+ " \"name\": \"Peeskillet\""
+ "}";
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();
}
Ich habe gerade eine einfache Employee
-Klasse mit einem id
- und name
-Feld zum Testen erstellt. Das funktioniert einwandfrei. Es zeigt das Bild, druckt die Inhaltsdisposition und druckt das Objekt Employee
.
Ich kenne mich mit Postman nicht so gut aus, also habe ich diese Tests zum Schluss gespeichert :-)
Es scheint auch gut zu funktionieren, wie Sie die Antwort sehen können "Cool Tools"
. Wenn wir uns jedoch die gedruckten Employee
-Daten ansehen, werden wir feststellen, dass sie null sind. Was seltsam ist, weil es mit der Client-API gut funktioniert hat.
Wenn wir uns das Vorschaufenster ansehen, werden wir das Problem sehen
Es gibt keinen Content-Type
- Header für den Hauptteil von emp
. Sie können in der Client-API sehen, dass ich es explizit festgelegt habe
MultiPart multipartEntity = new FormDataMultiPart()
.field("emp", empPartJson, MediaType.APPLICATION_JSON_TYPE)
.bodyPart(filePart);
Ich denke, das ist wirklich nur ein Teil einer vollständigen Antwort. Wie gesagt, ich kenne mich mit Postman nicht aus. Daher weiß ich nicht, wie man Content-Type
Für einzelne Körperteile einstellt. Das image/png
Für das Bild wurde automatisch für den Bildteil festgelegt (ich denke, es wurde nur durch die Dateierweiterung bestimmt). Wenn Sie dies herausfinden können, sollte das Problem gelöst sein. Bitte, wenn Sie herausfinden, wie das geht, posten Sie es als Antwort.
Grundlegende Konfigurationen:
Abhängigkeit:
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-multipart</artifactId>
<version>${jersey2.version}</version>
</dependency>
Client-Konfiguration:
final Client client = ClientBuilder.newBuilder()
.register(MultiPartFeature.class)
.build();
Serverkonfiguration:
// Create JAX-RS application.
final Application application = new ResourceConfig()
.packages("org.glassfish.jersey.examples.multipart")
.register(MultiPartFeature.class);
Wie Sie auf dem Postman-Client sehen können, können einige Clients den Inhaltstyp einzelner Teile nicht festlegen. Dies schließt den Browser hinsichtlich seiner Standardfunktionen ein, wenn FormData
(js) verwendet wird.
Wir können nicht davon ausgehen, dass der Client dies herausfindet. Wir können also beim Empfang der Daten den Inhaltstyp vor der Deserialisierung explizit festlegen. Zum Beispiel
@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);
}
Es ist ein wenig mehr Arbeit, um das POJO zu bekommen, aber es ist eine bessere Lösung, als den Kunden zu zwingen, zu versuchen, eine eigene Lösung zu finden.
Sie können auf die Image-Datei und Daten von einem Formular aus mit MULTIPART FORM DATA zugreifen.
@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) {}
}
}
}
Ich möchte einen Kommentar zu peeskillet hinzufügen, habe aber keine 50 Reputationspunkte und füge als Antwort hinzu:
Als ich die @peeskillet-Lösung mit dem Jersey-Client 2.21.1 ausprobierte, gab es 400 Fehler. Es hat funktioniert, als ich folgendes in meinen Client-Code eingefügt habe:
MediaType contentType = MediaType.MULTIPART_FORM_DATA_TYPE;
contentType = Boundary.addBoundary(contentType);
Response response = t.request().post(
Entity.entity(multipartEntity, contentType));
anstelle von fest codiertem MediaType.MULTIPART_FORM_DATA beim Aufruf nach der Anforderung.
Ihre ApplicationConfig sollte die MultiPartFeature.class von glassfish.jersey.media .. registrieren, um das Hochladen von Dateien zu ermöglichen
@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);
}