Expand my Community achievements bar.

Writing Files to the JCR using a Sling Servlet

Avatar

Employee

Here is a useful servlet following best practices to take a file from a client application and write it to the JCR. We follow best practices using the LoginService. Also, do not forget to set the Apache Sling User Mapper service to the appropriate user (for testing on a local instance, use admin). If you are using Archetype 10, the only additional dependency in Maven you need to add is:

<dependency>

  <groupId>commons-fileupload</groupId>

  <artifactId>commons-fileupload</artifactId>

  <version>1.2</version>

</dependency>

Thanks to Scott MacDonald, AEM Community Manager at Adobe, for the huge majority of this code.

Code:

//import java.io.BufferedReader;

import java.io.IOException;

import java.io.InputStream;

import java.rmi.ServerException;

import java.util.Calendar;

 

import org.apache.felix.scr.annotations.Property;

import org.apache.felix.scr.annotations.Reference;

import org.apache.felix.scr.annotations.sling.SlingServlet;

import org.apache.sling.api.SlingHttpServletRequest;

import org.apache.sling.api.SlingHttpServletResponse;

import javax.jcr.Session;

import javax.jcr.Node;

  

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import org.apache.sling.jcr.api.SlingRepository;

 

//This is a component so it can provide or consume services

@SlingServlet(paths="/bin/upfile", methods = "POST", metatype=true)

@Property(name = "sling.auth.requirements", value = "-/bin/upfile")

public class HandleFile extends org.apache.sling.api.servlets.SlingAllMethodsServlet {

private static final long serialVersionUID = 2598426539166789515L;

       

private Session adminSession;

@Reference

private SlingRepository repository;

 

private String clientLibPath = "";

 

/** Default log. */

protected final Logger log = LoggerFactory.getLogger(this.getClass());

      

//Inject a Sling ResourceResolverFactory

      

@Override

protected void doGet(SlingHttpServletRequest request, SlingHttpServletResponse response) throws ServerException, IOException {

        

         

     }

      

      

@Override

protected void doPost(SlingHttpServletRequest request, SlingHttpServletResponse response) throws ServerException, IOException {

        

      try

         {

         final boolean isMultipart = org.apache.commons.fileupload.servlet.ServletFileUpload.isMultipartContent(request);

          

           if (isMultipart) {

             final java.util.Map<String, org.apache.sling.api.request.RequestParameter[]> params = request.getRequestParameterMap();

             

             for (final java.util.Map.Entry<String, org.apache.sling.api.request.RequestParameter[]> pairs : params.entrySet()) {

                               

                 final org.apache.sling.api.request.RequestParameter[] pArr = pairs.getValue();

               

                 final org.apache.sling.api.request.RequestParameter param0 = pArr[0];

                 

                 //Determine if the posted value is a file or the JCR Path

                 boolean formField = param0.isFormField(); //Is this a form field or a posted file

                 

                 if (formField)

                 {

                     String libLoc = param0.getString(); 

                     clientLibPath = libLoc ; //Set the class member - its the first posted value from the client

                     log.info("FIELD VALUE IS: "+libLoc )  ;

                     

                 }

                 else

                 {

                     // final org.apache.sling.api.request.RequestParameter param1 = pArr[1];

                  final InputStream stream = param0.getInputStream();

                  String mimeType = param0.getContentType();

               

                  log.info("THE CONTENT TYPE IS: "+mimeType )  ;

                  

                  //Save the uploaded file into the Adobe CQ DAM

                  writeToClientLib(stream,param0.getFileName(),clientLibPath,mimeType  );

                 }

             }

           }

         }

          

         catch (Exception e) {

             e.printStackTrace();

         }

      

     }

      

    

//Save the uploaded file into the specified client lib path

private String writeToClientLib(InputStream is, String fileName, String path, String mimetype)

{

try

{

    //Invoke the adaptTo method to create a Session

  adminSession = repository.loginService(null, repository.getDefaultWorkspace());

     

    Node node = adminSession.getNode(path);  //Get the client lib node in which to write the posted file

    javax.jcr.ValueFactory valueFactory = adminSession.getValueFactory();            

    javax.jcr.Binary contentValue = valueFactory.createBinary(is);           

    Node fileNode = node.addNode(fileName, "nt:file");

    fileNode.addMixin("mix:referenceable");

    Node resNode = fileNode.addNode("jcr:content", "nt:resource");

    resNode.setProperty("jcr:mimeType", mimetype);

    resNode.setProperty("jcr:data", contentValue);

    Calendar lastModified = Calendar.getInstance();

    lastModified.setTimeInMillis(lastModified.getTimeInMillis());

    resNode.setProperty("jcr:lastModified", lastModified);

    adminSession.save();           

    adminSession.logout();

      

    // Return the path to the document that was stored in CRX.

    return fileNode.getPath();

}

catch(Exception e)

{

    e.printStackTrace();

}

return null;

}

  

}

1 Reply

Avatar

Level 1

There is no need to use the adminSession. Instead you can get the ResourceResolver from the request object and adapt it to a Session:

        ResourceResolver resourceResolver = request.getResourceResolver();

        Session session = resourceResolver.adaptTo(Session.class);

        Node node = session.getRootNode().getNode(path);

                 // IMPORTANT: note that you do not need to logout out of the session in this case