Upload File zu einem Webservice

internet

Top Contributor
Hallo,

ich möchte gerne mit JAX-RS einen Webservice schreiben, der mir eine Datei (i.d.R. ein Bild) entgegennimmt.

Wie muss ich die Methode hier annotieren?
Java:
    @POST
    @Path(/upload)
    @Produces(MediaType.APPLICATION_JSON)
public Response uploadFile(@QueryParam(file) Object myFile,[/CODE]

- was muss als @Produces rein?
- Anstatt ein Objekt vom Typ "Object", was muss ich als @QueryParam hinzufügen?

Generell:
Wie muss der Methodenkopf für das Vorhaben aussehen?
 
was muss als @Produces rein?
Der Typ des Inhalts, der zurückgesendet wird. Beim Upload schickst Du vermutlich nichts zurück, also ist auch keine Produces-Annotation notwendig.

Wie muss der Methodenkopf für das Vorhaben aussehen?
Java:
@POST
public Response uploadFile(InputStream is) /* ggf. throws IOException */ {
    /* InputStream verarbeiten */
    return Response.ok().build();
}
Den Dateinamen könntest Du z. B. als Path-Parameter übergeben, sofern das notwendig ist.
 
..oder falls zusätzliche Informationen zur Datei benötigt werden:
Java:
@POST
@Path("/fileupload")  // your Path or URL to call this service
@Consumes(MediaType.MULTIPART_FORM_DATA)
public Response uploadFile(
        @DefaultValue("true") @FormDataParam("enabled") boolean enabled, // additional data params
        @FormDataParam("file") InputStream inputStream, // file content
        @FormDataParam("file") FormDataContentDisposition fileDetail) { // additional file infos
     //read infos from fileDetail
    String fileName = fileDetail.getFileName();
    System.out.println(fileName);
    ...
 
..oder falls zusätzliche Informationen zur Datei benötigt werden:
Java:
@POST
@Path("/fileupload")  // your Path or URL to call this service
@Consumes(MediaType.MULTIPART_FORM_DATA)
public Response uploadFile(
        @DefaultValue("true") @FormDataParam("enabled") boolean enabled, // additional data params
        @FormDataParam("file") InputStream inputStream, // file content
        @FormDataParam("file") FormDataContentDisposition fileDetail) { // additional file infos
     //read infos from fileDetail
    String fileName = fileDetail.getFileName();
    System.out.println(fileName);
    ...

welche Lib verwendest du?
Ich finde kein @FormDataParam, sondern nur @FormParam (javax.ws.rs.FormParam)?
Sollte von Wildfly mitgeliefert werden...
 
Das dürfte von Jersey / JAX RS kommen:

und wie müsste das bei Wildfly aussehen?

Ebenfalls würde ich gerne 2 Parameter übergeben:
1. InputStream
2. Json Objekt

Sowas wie:

Java:
    public Response uploadFile(
            @FormDataParam InputStream inputStream,
            PicPictureDTO picPictureDTO) {

Das ganze würde ich gerne in Postman testen...
 
Also Wildfly bringt mit / nutzt RESTeasy oder nicht? Da würde man dann vermutlich auf diese Annotation verzichten. Wenn ich Dich richtig verstanden habe, geht es Dir auch erst einmal nur um den File Upload:



Das wäre da vermutlich mein Ansatz.
Ja, soweit ich weiß kommt da RestEasy mit...

Nein, ich möchte zwei Dinge übergeben - was nun eher das Problem ist...
1. Objekt von meiner Klasse PicPictureDTO (Json - Objekt?)
Java:
 {
        "colorFlag": "NONE",
        "fileName": "Test.jpg"
 }
2. InputStream

Ich hatte auch zunächst überlegt nur das PicPictureDTO zu übergeben, welches dann ein Feld: InputStream inputStream hat, aber das lässt sich wohl nicht mit Postman wirklich testen...

Ich denke so würde es gehen, wenn ich nur das File habe:
1634749519409.png

Problem ist aber nun, dass ich zusätzlich auch noch das PicPictureDTO - Objekt übergeben möchte...
Any ideas?


Edit:
gerade getestet: MultipartFormDataInput finde ich auch nicht in meinem Projekt...
Muss ich hier eine zusätzliche API in mein Maven Projekt aufnehmen?
 
Zuletzt bearbeitet:
Du könntest die Bilder Base64 enkodieren und in das json einbetten. Ist nicht optimal in Bezug auf übertragene Daten, aber u.U. der einfachste Weg.

gerade getestet: MultipartFormDataInput finde ich auch nicht in meinem Projekt...
Muss ich hier eine zusätzliche API in mein Maven Projekt aufnehmen?
Direkt er erste Code-Block im Link von @kneitzel listet die nötigen Dependencies auf.
 
Ich arbeite normalerweise nicht mit dem Wildfly. Generell entwickelt man doch aber nicht gegen einen bestimmten Server oder Hersteller. Wir erstellen natürlich auch auf den Hersteller zugeschnittene Konfigurationsdateien. Dies sieht der Standard expliziet vor. Der Rest ist jedoch Sache der Anwendung. Zugegeben ist es eher selten, dass man den Server wechselt. Test, Entwicklung und Produktion laufen bei uns aber oft auf ganz unterschiedlichen Systemen. Meist sind nur Produktion und Vor-Produktion identisch.
 
Beispiel nutzt ja auch eine konkrete Implementierung
Natürlich bezieht sich mein Beispiel auf ein konkrete Implementierung - aber eine die die Anwendung mitbringt und nicht der Server. Ich wäre bspw. auch auf ewig an die veralteten Bibliotheken des Servers gebunden, wenn ich dessen API verwenden würde. Ich könnte auch nie auf eine DB oder einen Storage zurückgreifen, wenn der Server den Treiber nicht mitliefert. Das ist ja das Konzept von EAR, man wird unabhängig vom Server, dieser muss lediglich dem JEE-Standard entsprechen.
 
Rennt man dann nicht teilweise in Probleme, weil es Überschneidungen gibt?

Du bindest eine Implementierung ein und nutzt es nun auf einem Server, der noch eine andere Implementierung hat (und sei es nur eine ältere?). Damit hast du dann ggf. unterschiedliche Klassen mit gleichem Namen, oder übersehe ich da jetzt etwas?
 
Natürlich bezieht sich mein Beispiel auf ein konkrete Implementierung - aber eine die die Anwendung mitbringt und nicht der Server. Ich wäre bspw. auch auf ewig an die veralteten Bibliotheken des Servers gebunden, wenn ich dessen API verwenden würde. Ich könnte auch nie auf eine DB oder einen Storage zurückgreifen, wenn der Server den Treiber nicht mitliefert. Das ist ja das Konzept von EAR, man wird unabhängig vom Server, dieser muss lediglich dem JEE-Standard entsprechen.
Du deployst zusammen mit deiner Anwendung jeweils noch eine JEE-Implementierung und ignorierst die vom Server bereitgestellte? 😵 Das führt doch das ganze Application-Server-Konzept ad absurdum?

Bei Datenbank-Treibern etc ist das ja verständlich, die sind ja nicht Teil von JEE – aber grad eine Jax-RS-Implementierung stellt der Server ja extra bereit, hat die mit der restlichen Implementierung integriert, bietet passende Konfigurationen etc...


Das ist ja dann auch eine ganz explizite Entscheidung, nicht gegen den Standard zu entwickeln – warum dann überhaupt JEE?
 
Rennt man dann nicht teilweise in Probleme, weil es Überschneidungen gibt?

Du bindest eine Implementierung ein und nutzt es nun auf einem Server, der noch eine andere Implementierung hat (und sei es nur eine ältere?). Damit hast du dann ggf. unterschiedliche Klassen mit gleichem Namen, oder übersehe ich da jetzt etwas?
Eigentlich ist das kein Problem, da man das Classloading beeinflussen kann. Es ist bspw. möglich einzustellen verwende Package xyz ausschließlich aus meiner Anwendung. Als Anfänger ist das etwas gewöhnungsbedürftig weil man solche Fehlermeldungen noch nicht gesehen hat. Wenn man es aber einmal verstanden hat, ist das kein Problem.
 
Du deployst zusammen mit deiner Anwendung jeweils noch eine JEE-Implementierung und ignorierst die vom Server bereitgestellte? 😵 Das führt doch das ganze Application-Server-Konzept ad absurdum?

Bei Datenbank-Treibern etc ist das ja verständlich, die sind ja nicht Teil von JEE – aber grad eine Jax-RS-Implementierung stellt der Server ja extra bereit, hat die mit der restlichen Implementierung integriert, bietet passende Konfigurationen etc...


Das ist ja dann auch eine ganz explizite Entscheidung, nicht gegen den Standard zu entwickeln – warum dann überhaupt JEE?
Es ist möglich Resourcen und änliches vom Server zu verwenden, z.B.: Datasources, JMX, Mail, Timer etc.. Genauso ist aber möglich z.B.: ein komplett anders JPA zu verwenden als der Server mitbringt. Da ist nichts am Standard vorbei, nur an den Bugs und veralteten Bibliotheken. Der JEE-Standard sieht das IMHO sogar vor. Es kann bestimmt jeder nachvollziehen, wenn man Hibernate kennt und dann auf dem Weblogic landet. Dort wird EclipseLink als JPA verwendet. Im Vergleich zu Hibernate ist das einfach furchtbar und immer hinter den Standard den es eigentlich verspricht. Zumindest war es in der Vergangenheit so. Zum Glück gibt es jetzt Spring Boot - das läuft als EAR auch auf dem Weblogic. Noch besser funktioniert es wenn man ganz auf JEE verzichten kann.
 
Das Problem mit dem Austauschen ist. Wenn man weiß was man tut, geht das. Wenn man es nicht weiß und versucht sich aus Stackoverflow, JBoss Doku & Co das zusammenzukopieren - Good Luck.

Java EE Server sind schwergewichtige Monster mit einem Haufen schwarzer Magie drin, wo man schon genau wissen muss man tut. Der Jboss hat javaee7-api? Du willst aber Microprofile Metrics mit JSON-Ausgabe in einer neueren Version? Pech gehabt, weil die JSON-Libraries die man dafür braucht erst in javaee8 drin sind und es gibt so lustige MethodNotFoundExceptions zur Laufzeit. man läuft da leicht in Probleme rein.

Deswegen bin ich mittlerweile kein Freund mehr von den Schwergewichtigen Java-EE Servern. Sie bringen zu viel mit und es ist zu aufwendig, wenn das nicht passt. Und das man mehr als eine größere Anwendung auf einem JBoss laufen hat ist nach meinem dafürhalten eh die Ausnahme. Sprich es gilt meisten 1 Server = 1 Anwendung. Dann kann ich auch gleich auf Spring Boot oder ähnliches setzen und den Server komplett mitbringen. Dann hab ich wenigstens auch die Gewissheit das über alle Stages die verwendete Software die gleiche ist und nicht in Test JBoss 7.3 und in Produktion 7.1
 

Zurück
Oben