Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JAX-RS FileUpload with Apache CXF

I'm trying to upload a file with JAX-RS and TomEE's Apache CXF implementation (2.6.14), but the uploaded file is always null.

Here is the code:

  @POST
  @Path("/upload")
  @Consumes(MediaType.MULTIPART_FORM_DATA)
  public Response uploadFile(@Multipart(value = "file") @NotNull Attachment attachment) throws UnsupportedEncodingException {
    try {

      System.out.println(attachment);

      return Response.ok("file uploaded").build();

    } catch (Exception ex) {
      logger.error("uploadFile.error():", ex);
      return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
    }
  }

and a very easy HTML-file for the upload:

<form action="http://127.0.0.1:8080/eegrating/restapi/cashflowparameter/upload" method="post" enctype="multipart/form-data">
    <p>File:<br>
        <input name="file" type="file" size="50" maxlength="100000" accept="text/*">
        <input type="submit" name="Submit" value="Send">
    </p>
</form>

The request header looks fine:

------WebKitFormBoundaryOCleIjB2JgeySK0w Content-Disposition: form-data; name="file"; filename="git.txt" Content-Type: text/plain

But the attachment is always null. Any suggestions? Thanks in advance.

like image 458
VWeber Avatar asked Jul 21 '14 07:07

VWeber


People also ask

Is Apache CXF a JAX-RS?

Overview. This tutorial introduces Apache CXF as a framework compliant with the JAX-RS standard, which defines support of the Java ecosystem for the REpresentational State Transfer (REST) architectural pattern.

What is Apache CXF used for?

Apache CXF™ is an open source services framework. CXF helps you build and develop services using frontend programming APIs, like JAX-WS and JAX-RS. These services can speak a variety of protocols such as SOAP, XML/HTTP, RESTful HTTP, or CORBA and work over a variety of transports such as HTTP, JMS or JBI.

What is meant by JAX-WS and JAX-RS?

JAX-WS represents SOAP. JAX-RS represents REST.


2 Answers

First, are you using Apache TomEE with JAX-RS?, if not you should, because this bundles JAX-RS. Try with this code. I'm using CXF specific features, I tested and works well. This resource just produces an HTML result, you can adapt it of course. As you see I referenced the CXF dependency as provided because TomEE includes it. I'm posting every file needed.

No web.xml file.

META-INF/context.xml

<?xml version="1.0" encoding="UTF-8"?>
<Context antiJARLocking="true" path="/FileUpload_2"/>

index.jsp

<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>JSP Page</title>
    </head>
    <body>
        <form method="POST" enctype="multipart/form-data"
              action="/FileUpload_2/web/upload">
            File to upload: <input type="file" name="upfile"><br/>
            Notes about the file: <input type="text" name="note"><br/>
            <br/>
            <input type="submit" value="Press"> to upload the file!
        </form>

    </body>
</html>

upload.MyApplication.java

package upload;

import java.util.*;
import javax.ws.rs.*;
import javax.ws.rs.core.*;

@ApplicationPath("web")
public class MyApplication extends Application {

    @Override
    public Set<Class<?>> getClasses() {
        return new HashSet<Class<?>>(Arrays.asList(UploadResource.class  ));
    }

}

upload.UploadResource.java

package upload;
import java.io.*;
import java.nio.file.*; 
import javax.ws.rs.*;
import javax.ws.rs.Path;
import javax.ws.rs.core.*;
import org.apache.cxf.jaxrs.ext.multipart.*; 

public class UploadResource {

    @POST
    @Path("/upload")
    @Produces(MediaType.TEXT_HTML)
    @Consumes(MediaType.MULTIPART_FORM_DATA)
    public String uploadFile(@Multipart("note") String note, 
     @Multipart("upfile") Attachment attachment) throws IOException {

       String filename = attachment.getContentDisposition().getParameter("filename");

        java.nio.file.Path path = Paths.get("c:/" + filename);
        Files.deleteIfExists(path);
        InputStream in = attachment.getObject(InputStream.class);

       Files.copy(in, path);
       return "uploaded " + note;  
    }                        

}

pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.mycompany</groupId>
    <artifactId>FileUpload_2</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>war</packaging>

    <name>FileUpload_2</name>

    <properties>
        <endorsed.dir>${project.build.directory}/endorsed</endorsed.dir>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-rt-frontend-jaxrs</artifactId>
            <version>2.6.14</version>
            <scope>provided</scope>
            <exclusions>
                <exclusion>
                    <groupId>com.sun.xml.bind</groupId>
                    <artifactId>jaxb-impl</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>javax.ws.rs</groupId>
                    <artifactId>jsr311-api</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>wsdl4j</groupId>
                    <artifactId>wsdl4j</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.apache.ws.xmlschema</groupId>
                    <artifactId>xmlschema-core</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.codehaus.woodstox</groupId>
                    <artifactId>woodstox-core-asl</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.apache.geronimo.specs</groupId>
                    <artifactId>geronimo-javamail_1.4_spec</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.apache.cxf</groupId>
                    <artifactId>cxf-rt-transports-http</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.apache.cxf</groupId>
                    <artifactId>cxf-rt-core</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.apache.cxf</groupId>
                    <artifactId>cxf-rt-bindings-xml</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.apache.cxf</groupId>
                    <artifactId>cxf-api</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>javax</groupId>
            <artifactId>javaee-web-api</artifactId>
            <version>6.0</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>2.3.2</version>
                <configuration>
                    <source>1.6</source>
                    <target>1.6</target>
                    <compilerArguments>
                        <endorseddirs>${endorsed.dir}</endorseddirs>
                    </compilerArguments>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-war-plugin</artifactId>
                <version>2.1.1</version>
                <configuration>
                    <failOnMissingWebXml>false</failOnMissingWebXml>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-dependency-plugin</artifactId>
                <version>2.1</version>
                <executions>
                    <execution>
                        <phase>validate</phase>
                        <goals>
                            <goal>copy</goal>
                        </goals>
                        <configuration>
                            <outputDirectory>${endorsed.dir}</outputDirectory>
                            <silent>true</silent>
                            <artifactItems>
                                <artifactItem>
                                    <groupId>javax</groupId>
                                    <artifactId>javaee-endorsed-api</artifactId>
                                    <version>6.0</version>
                                    <type>jar</type>
                                </artifactItem>
                            </artifactItems>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

</project>
like image 50
Nestor Hernandez Loli Avatar answered Oct 15 '22 07:10

Nestor Hernandez Loli


For cxf specific (not jersey) your code could be as below

@POST
@Path("/upload")
@Consumes(MediaType.MULTIPART_FORM_DATA)
public Response uploadFile(MultipartBody body) throws UnsupportedEncodingException {
   try {
      for(Attachment attachment : body.getAllAttachments()){
          System.out.println(attachment);
      }
      return Response.ok("file uploaded").build();

   } catch (Exception ex) {
       logger.error("uploadFile.error():", ex);
       return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
   }
}

your code is not working cause we have to pass specific contentId to the @Multipart. the code look like as below

note*: contentId is not your file property name that you are sending from client

@POST
@Path("/upload")
@Consumes(MediaType.MULTIPART_FORM_DATA)
public Response uploadFile(@Multipart(value="spcfic contentId", type="application/octet-stream") Attachment attachment) throws UnsupportedEncodingException {
    ...
    ...
}

I would suggest to use MultipartBody instead of @Multipart

refer : http://cxf.apache.org/docs/jax-rs-multiparts.html

I shall be glad for any improvement or rectifying the content of the post :)

like image 23
Ram Avatar answered Oct 15 '22 08:10

Ram