Handling File Upload in Adobe CQ

Published on by Dan KlcoPicture of Me Dan Klco
This was also posted on: labs.sixdimensions.com, however 6D Global Technologies decided to remove my authoring credit, which seems unethical.

You need to handle a file upload in Adobe CQ.  So, you notice CQ already has Apache Commons FileUpload installed, so you decide to use it to handle the file upload.

You write your servlet code and end up with something like this:

// Check that we have a file upload request
final boolean isMultipart = ServletFileUpload.isMultipartContent(request);
PrintWriter out = null;
try {
  out = response.getWriter();
  if (isMultipart) {
	// Create a new file upload handler
	final ServletFileUpload upload = new ServletFileUpload();
	// Parse the request
	final FileItemIterator iter = upload.getItemIterator(request);
	while (iter.hasNext()) {
	  final FileItemStream item = iter.next();
	  final String name = item.getFieldName();
	  final InputStream stream = item.openStream();
	  if (item.isFormField()) {
		out.println("Form field " + name + " with value " + Streams.asString(stream) + " detected.");
	  } else {
		out.println("File field " + name + " with file name " + item.getName() + " detected.");
	  }
	}
  }

After you build your code and deploy it to CQ, you try to upload a file to test and boom!  You get the following error:

java.lang.IllegalStateException: Request Data has already been read

What happened?  Your code is correct, and you aren’t already reading the request data, so why are you getting an error?  Well, Sling reads the file content automatically, so the your code attempts to read in the request data twice.

Instead of reading the contents through FileUpload, you can retrieve the file contents from the Sling API.  Sling makes the uploaded files and all parameters available from the SlingHttpServletRequest.getRequestParameterMap method, which returns a RequestParamterMap.  Simply iterate over the parameters to retrieve the file and any parameters passed into the request.

// Check that we have a file upload request
final boolean isMultipart = ServletFileUpload.isMultipartContent(request);
PrintWriter out = null;
try {
  out = response.getWriter();
  if (isMultipart) {
	final Map<String, RequestParameter[]> params = request.getRequestParameterMap();
	for (final Map.Entry<String, RequestParameter[]> pairs : params.entrySet()) {
	  final String k = pairs.getKey();
	  final RequestParameter[] pArr = pairs.getValue();
	  final RequestParameter param = pArr[0];
	  final InputStream stream = param.getInputStream();
	  if (param.isFormField()) {
		out.println("Form field " + k + " with value " + Streams.asString(stream) + " detected.");
	  } else {
		out.println("File field " + k + " with file name " + param.getFileName() + " detected.");
	  }
	}
  }

Tags


comments powered by Disqus