Submit a file using POST request in CRX

This simple example shows how we can submit a file using a POST request to a JSP from an html form. I used CRXDE for creating the project.

Create a new project in CRXDE by right clicking on the Project Navigator page and selecting Build->Create Project. Give a project name and the package name that you will be using. I will be using simplePOSTRequest as the project name.

  • A new folder is created under apps with the name simplePOSTRequest. In CRXDE Lite you will find under the content node that a new node is created with the name “simplePOSTRequest”. On the node the slingResourceType property is set which points to simplePOSTRequest/components/sample.
  • In simplePOSTRequest/components/sample, under the apps folder you will find a components folder with html.jsp page already created. This is the page that is invoked when you go to http://localhost:7402/simplePOSTRequest.html.

Now modify the html page and add a simple html form which takes a file as in input and has a submit button.  Save the project.

Now, go to http://localhost:7402/simplePOSTRequest.html and select a file and click upload. You will get a 200 OK status message which means that the request was successful (See image below).

We did not have any POST request handling logic at this point, so where did the file go? If you go to CRXDE Lite, you will see under the simplePOSTRequest node in content node that a new node is created. The name of the node is the name we specified for the File input type in the html form.

If we want to create a JSP file and want the POST request to be redirected to that JSP create a POST.jsp file under apps/simplePOSTRequest/components/sample.

Now if you click the upload button, you will see the new page will be invoked and no nodes will be created in the crx. You can access the form data from the HttpServletRequest or SlingHttpServletRequest object in POST.jsp.

Here is the POST.jsp that displays the submitted file details. (Click to enlarge)

 

10 Responses to Submit a file using POST request in CRX

  1. Ryan Lunka says:

    How would you recommend making the POST URL configurable? The code above (without changing it) would only work on that one server, because the location is hard coded.

  2. Nikhil says:

    You can change the urls to “http://”+request.getServerName().trim()+”:7402/simplePOSTRequest”.
    This way the requests are routed to the server application is hosted on.

  3. Aaron says:

    Our organization spent a lot of time trying to make this functionality work, but were told (repeatedly) by support that trying to write custom form handlers like this doesn’t conform to RESTful ideals and thus shouldn’t be done at all.

    The problem with how you’ve implemented this here is that subsequent cq:include or sling:include calls will cause components to be POSTed to as well, preventing you from wrapping your form in an existing template or production website.

    Our workaround was to store the POST data as a request attribute, create a custom request handler to override the request method, and forward the request to the new handler within POST.jsp.

  4. First, the action should really be a relative URL, such as “/simplePOSTRequest”.

    Secondly, it is a good approach to try to avoid writing custom POST handlers (such as the JSP above) and go as far with the default sling post servlet as possible. Then you only have to think about the content model (i.e. where to post to and what parameters to send, incl. the right resource types), maybe in conjunction with a sling post processor to do some cleanup/validation “after” the post.

  5. Ryan Lunka says:

    Thanks Nikhil! That’s what I was looking for.

    Aaron and/or Alexander, if you don’t consider this a best practice, could you elaborate further on your alternative idea? I’m relatively new to RESTful architecture and Sling, so I would appreciate a dumbed down explanation, if you could provide one.

    • Gary Gilchrist says:

      +1 🙂 If anyone else is willing to write up their best practice I’d be happy to cross post it here linking to your article under our Guest Posts section. Thanks, Nikhil for posting this one.

  6. Paul Flory says:

    On a related note, I’ve always found this page to be helpful:
    http://sling.apache.org/site/manipulating-content-the-slingpostservlet-servletspost.html

  7. Felix says:

    I just want to reiterate what Alex said: Don’t write your own POST request processing just for a thing as simple as uploading a file. The Sling’s own POST request processing has elaborate functionality to handling POST requests including file uploads. Refer to Sling documentation pointed to by Paul for the whole scoop.

    For short: Uploading a file to Sling and any Sling-based system such as CRX or Communiqué 5 is as easy as sending a POST request to any URL. The will be stored in a node whose name is derived from the parameter name below that URL.

    Of course you still can implement your own POST request processor, but in most of the cases you don’t need to …

  8. Justin says:

    @Aaron – I think the problem you’re referring to is that when you create a custom POST handler, you may be breaking other components/applications which depend upon the default POST servlet. This is especially true with CQ where the authoring interface uses the default POST servlet. In these circumstances, if you really NEED a custom POST handler, then you should register it using a selector. That way, POSTs to /foo/bar.html go to the default POST servlet and POSTs to /foo/bar.myselector.html go to your custom POST handler.

    This technique gives you the best of both worlds – the default behavior for the vast majority of the time and some custom behavior for the one case where you need it.

    The second example in this blog post is a good example of that where it would probably make more sense for an “info” page to be returned when posting to simplePOSTRequest.info.html.

  9. Sarwar Bhuiyan says:

    The other thing you can do is put an input element with name “:redirect” and set the value to the redirect page you want to go to after the successful upload. That wouldn’t require the POST.jsp if all you need is the file uploaded or some properties set on a node.

    Sarwar