Expand my Community achievements bar.

Submissions are now open for the 2026 Adobe Experience Maker Awards.
SOLVED

Issue with @FormDataParam in Jersey Multipart Form-Data on AEM Cloud

Avatar

Level 1

Hi all,

I am working with AEM as a Cloud Service and trying to handle multipart form-data using Jersey's @FormDataParam annotation for file uploads. However, I am facing issues with this approach, and I wanted to check if anyone has encountered similar problems or can provide a solution.

Here are the details:

  1. Environment: AEM as a Cloud Service

  2. Library: Jersey 2.25.1(jersey-media-multipart) for handling file uploads via @FormDataParam.

  3. Issue: The @FormDataParam annotation does not seem to work as expected in AEM Cloud. The form data, including files, is not parsed correctly, and the parameters are not being extracted.

Here’s the code I’m using:

 

@path("/upload")
public class FileUploadService {
@post
@path("/file")
@Consumes(MediaType.MULTIPART_FORM_DATA)
@Produces(MediaType.APPLICATION_JSON)
public Response uploadFile(
@FormDataParam("file") InputStream uploadedInputStream,
@FormDataParam("file") FormDataContentDisposition fileDetail,
@FormDataParam("description") String description) {String fileName = fileDetail.getFileName();

// Logic to save the file and return a response
return Response.ok("{\"message\": \"File uploaded successfully\"}").build();
}
}

Observations:

  • The @FormDataParam annotation is not properly extracting the form data or file content.

  • The server doesn’t recognize the multipart form fields as expected.

  • I’ve verified that the form submission is correct (using an HTML form with enctype="multipart/form-data"), but still, the parameters don’t get parsed.

Questions:

  1. Is @FormDataParam supported in AEM Cloud? If not, is there a recommended approach for handling multipart form-data uploads in AEM Cloud using Jersey or Sling Servlets?

  2. Are there any specific configurations or limitations in AEM Cloud that could prevent Jersey's multipart handling from working properly?

Any insights or suggestions would be greatly appreciated!

Thanks in advance.

 

1 Accepted Solution

Avatar

Correct answer by
Community Advisor

Hi @DikshaCh2,

I haven't experienced in my past experience - however, when I researched bit on this found few things:

AEMaaCS uses Apache Sling as the request-processing layer, not a full Jersey runtime. While Jersey might work in on-prem or AMS setups (with custom dependencies), AEMaaCS restricts runtime behavior.

So, instead of Jersey, may be could give a try using a Sling POST Servlet and parse the multipart request manually?

Like: 

@Component(service = Servlet.class,
           property = {
             "sling.servlet.methods=POST",
             "sling.servlet.paths=/bin/upload-file",
             "sling.servlet.extensions=json"
           })
public class FileUploadServlet extends SlingAllMethodsServlet {

    @Override
    protected void doPost(SlingHttpServletRequest request, SlingHttpServletResponse response)
            throws ServletException, IOException {

        boolean isMultipart = ServletFileUpload.isMultipartContent(request);
        if (!isMultipart) {
            response.setStatus(SlingHttpServletResponse.SC_BAD_REQUEST);
            response.getWriter().write("{\"error\": \"Not a multipart request\"}");
            return;
        }

        try {
            ServletFileUpload upload = new ServletFileUpload();
            FileItemIterator iter = upload.getItemIterator(request);

            while (iter.hasNext()) {
                FileItemStream item = iter.next();
                String fieldName = item.getFieldName();

                if (!item.isFormField() && "file".equals(fieldName)) {
                    InputStream fileContent = item.openStream();
                    String fileName = item.getName();

                    // Save to DAM or elsewhere
                } else if ("description".equals(fieldName)) {
                    InputStream stream = item.openStream();
                    String description = IOUtils.toString(stream, StandardCharsets.UTF_8);
                }
            }

            response.getWriter().write("{\"message\": \"Upload successful\"}");
        } catch (Exception e) {
            response.setStatus(SlingHttpServletResponse.SC_INTERNAL_SERVER_ERROR);
            response.getWriter().write("{\"error\": \"" + e.getMessage() + "\"}");
        }
    }
}

Jus in case if you missed:

In your core/pom.xml, add:

<dependency>
  <groupId>commons-fileupload</groupId>
  <artifactId>commons-fileupload</artifactId>
  <version>1.4</version>
</dependency>

Also make sure it’s included in your OSGi bundle (check bnd.bnd or maven-bundle-plugin exports if needed).


Santosh Sai

AEM BlogsLinkedIn


View solution in original post

1 Reply

Avatar

Correct answer by
Community Advisor

Hi @DikshaCh2,

I haven't experienced in my past experience - however, when I researched bit on this found few things:

AEMaaCS uses Apache Sling as the request-processing layer, not a full Jersey runtime. While Jersey might work in on-prem or AMS setups (with custom dependencies), AEMaaCS restricts runtime behavior.

So, instead of Jersey, may be could give a try using a Sling POST Servlet and parse the multipart request manually?

Like: 

@Component(service = Servlet.class,
           property = {
             "sling.servlet.methods=POST",
             "sling.servlet.paths=/bin/upload-file",
             "sling.servlet.extensions=json"
           })
public class FileUploadServlet extends SlingAllMethodsServlet {

    @Override
    protected void doPost(SlingHttpServletRequest request, SlingHttpServletResponse response)
            throws ServletException, IOException {

        boolean isMultipart = ServletFileUpload.isMultipartContent(request);
        if (!isMultipart) {
            response.setStatus(SlingHttpServletResponse.SC_BAD_REQUEST);
            response.getWriter().write("{\"error\": \"Not a multipart request\"}");
            return;
        }

        try {
            ServletFileUpload upload = new ServletFileUpload();
            FileItemIterator iter = upload.getItemIterator(request);

            while (iter.hasNext()) {
                FileItemStream item = iter.next();
                String fieldName = item.getFieldName();

                if (!item.isFormField() && "file".equals(fieldName)) {
                    InputStream fileContent = item.openStream();
                    String fileName = item.getName();

                    // Save to DAM or elsewhere
                } else if ("description".equals(fieldName)) {
                    InputStream stream = item.openStream();
                    String description = IOUtils.toString(stream, StandardCharsets.UTF_8);
                }
            }

            response.getWriter().write("{\"message\": \"Upload successful\"}");
        } catch (Exception e) {
            response.setStatus(SlingHttpServletResponse.SC_INTERNAL_SERVER_ERROR);
            response.getWriter().write("{\"error\": \"" + e.getMessage() + "\"}");
        }
    }
}

Jus in case if you missed:

In your core/pom.xml, add:

<dependency>
  <groupId>commons-fileupload</groupId>
  <artifactId>commons-fileupload</artifactId>
  <version>1.4</version>
</dependency>

Also make sure it’s included in your OSGi bundle (check bnd.bnd or maven-bundle-plugin exports if needed).


Santosh Sai

AEM BlogsLinkedIn