Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>Here is the solution that I have made, BalusC helped me a lot to developed it.</p> <h2>Platform and Framework</h2> <ul> <li>Uploadify v3.2</li> <li>JSF 1.2</li> <li>jQuery 1.8.3</li> <li>WebLogic 10.3.5.0</li> <li>Apache Commons Fileupload 1.2.2</li> </ul> <h2>Problem with multipart request</h2> <p>JSF 1.2 is cannot handle the multipart request. So if the <code>&lt;h:form/&gt;</code> contains <code>enctype="multipart/form-data"</code> as attribute then the <code>action</code> method of command component like <code>&lt;h:commandButton/&gt;</code> will not fire. The solution is to create a Filter which will work together with <code>Faces Servlet</code> and handle the mutipart request explicitly. Here is the filter:</p> <pre><code>package com.mhis.massupload.filter; import java.io.IOException; import java.util.Collections; import java.util.Enumeration; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequestWrapper; import org.apache.commons.fileupload.FileItem; import org.apache.commons.fileupload.disk.DiskFileItemFactory; import org.apache.commons.fileupload.servlet.ServletFileUpload; public class MultipartFilter implements Filter { private FilterConfig filterConfig = null; public void init(FilterConfig filterConfig) throws ServletException { this.filterConfig = filterConfig; } public void destroy() { filterConfig = null; } public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { if (!(request instanceof HttpServletRequest)) { chain.doFilter(request, response); return; } HttpServletRequest httpRequest = (HttpServletRequest)request; boolean isMultipartContent = ServletFileUpload.isMultipartContent(httpRequest); if (!isMultipartContent) { chain.doFilter(request, response); return; } try { DiskFileItemFactory factory = new DiskFileItemFactory(); ServletFileUpload upload = new ServletFileUpload(factory); upload.setHeaderEncoding("UTF-8"); upload.setSizeMax(-1); List&lt;FileItem&gt; items = upload.parseRequest(httpRequest); final Map&lt;String, String[]&gt; parameterMap = new HashMap&lt;String, String[]&gt;(); for (FileItem item : items) { if (item.isFormField()) { processFormField(item, parameterMap); } } chain.doFilter(new HttpServletRequestWrapper(httpRequest) { public Map&lt;String, String[]&gt; getParameterMap() { return parameterMap; } public String[] getParameterValues(String name) { return (String[])parameterMap.get(name); } public String getParameter(String name) { String[] params = getParameterValues(name); if (params == null) { return null; } return params[0]; } public Enumeration&lt;String&gt; getParameterNames() { return Collections.enumeration(parameterMap.keySet()); } }, response); } catch (Exception ex) { ServletException servletException = new ServletException(); servletException.initCause(ex); throw servletException; } } private void processFormField(FileItem formField, Map&lt;String, String[]&gt; parameterMap) { String name = formField.getFieldName(); String value = formField.getString(); String[] values = parameterMap.get(name); if (values == null) { parameterMap.put(name, new String[] { value }); } else { int length = values.length; String[] newValues = new String[length + 1]; System.arraycopy(values, 0, newValues, 0, length); newValues[length] = value; parameterMap.put(name, newValues); } } } </code></pre> <p>The configuration of this filter in the web.xml is:</p> <pre><code>&lt;filter&gt; &lt;filter-name&gt;MultipartFilter&lt;/filter-name&gt; &lt;filter-class&gt;com.mhis.massupload.filter.MultipartFilter&lt;/filter-class&gt; &lt;/filter&gt; &lt;filter-mapping&gt; &lt;filter-name&gt;MultipartFilter&lt;/filter-name&gt; &lt;servlet-name&gt;Faces Servlet&lt;/servlet-name&gt; &lt;/filter-mapping&gt; </code></pre> <h2>Javasctipt for Uploadify</h2> <pre><code>$('#uploadify').uploadify({ 'auto': false, 'buttonText' : 'Browse', 'fileSizeLimit': 0, 'swf': 'uploadify/uploadify.swf', 'uploader': '${pageContext.request.contextPath}/uploadservlet?key=&lt;h:outputText value="#{uploadBean.key}" /&gt;', 'onQueueComplete' : function(queueData) { $('.checkIn').click(); } }); </code></pre> <p>In my requirement I need to upload all the files when the submit button of the form has been clicked not at then time when the files are added in the queue. That is why I have set <code>'auto': false</code>. The uploadify folder has been put inside the Web-Content of my project and for that this plugin was unable to find the <code>uploadify.swf</code> file and the image of the cancel button. I have to modify the <code>jquery.uploadify.js</code>'s line no 99 and I have changed it as <code>swf: 'uploadify/uploadify.swf'</code> and also the <code>uploadify.css</code>'s line no 74 and I have changed it to:</p> <pre><code>.uploadify-queue-item .cancel a { background: url('../uploadify/uploadify-cancel.png') 0 0 no-repeat; float: right; height: 16px; text-indent: -9999px; width: 16px; } </code></pre> <p>The <code>background</code> was set to <code>url('../img/uploadify-cancel.png') 0 0 no-repeat;</code>, but I don't have img folder.</p> <h2>Servlet</h2> <p>For the uploading the files I have used a <code>Servlet</code>, viz <code>UplaodServlet</code>; the configuration of this servlet is:</p> <pre><code>&lt;servlet&gt; &lt;servlet-name&gt;UploadServlet&lt;/servlet-name&gt; &lt;servlet-class&gt;com.mhis.massupload.servlet.UploadServlet&lt;/servlet-class&gt; &lt;/servlet&gt; &lt;servlet-mapping&gt; &lt;servlet-name&gt;UploadServlet&lt;/servlet-name&gt; &lt;url-pattern&gt;/uploadservlet&lt;/url-pattern&gt; &lt;/servlet-mapping&gt; </code></pre> <p>The <code>uploadservlet</code> has been used as the <code>uploader</code> attribute of the <code>uploadify</code>'s config. I need also to pass a unique key as request parameter of the <code>Servlet</code>. The code for the <code>Servlet</code> is:</p> <pre><code>package com.mhis.massupload.servlet; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.logging.Logger; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.fileupload.FileItem; import org.apache.commons.fileupload.disk.DiskFileItemFactory; import org.apache.commons.fileupload.servlet.ServletFileUpload; public class UploadServlet extends HttpServlet { @SuppressWarnings("compatibility:-6472602315203858426") private static final long serialVersionUID = -3714619333861571457L; private transient Logger log = Logger.getLogger(getClass().getName()); @Override public void init(ServletConfig config) throws ServletException { super.init(config); } @Override public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException { boolean isMultipartContent = ServletFileUpload.isMultipartContent(request); if (!isMultipartContent) { return; } FileItem fileField = null; try { DiskFileItemFactory factory = new DiskFileItemFactory(); ServletFileUpload upload = new ServletFileUpload(factory); upload.setHeaderEncoding("UTF-8"); upload.setSizeMax(-1); List&lt;FileItem&gt; items = upload.parseRequest(request); final Map&lt;String, String[]&gt; parameterMap = new HashMap&lt;String, String[]&gt;(); for (FileItem item : items) { if (!item.isFormField()) { fileField = item; } } } catch (Exception ex) { log.severe(ex.getMessage()); } if (fileField == null) { return; } String key = request.getParameter("key"); List&lt;FileItem&gt; fileFields = (List&lt;FileItem&gt;)getServletContext().getAttribute(key); if (fileFields == null) { fileFields = new ArrayList&lt;FileItem&gt;(); getServletContext().setAttribute(key, fileFields); } fileFields.add(fileField); } } </code></pre> <p>I am unable to use <code>Session</code> to put the information about the uploaded file, so I have used <code>ServletContext</code> instead. For more info refer <a href="https://stackoverflow.com/questions/14275732/passing-value-from-servlet-to-jsf-action-method-in-weblogic">here</a>.</p> <h2>JSF page and Upload button</h2> <p>As my need is to upload the files only when the form is submitted after the validation, so I have set <code>'auto': false</code> in the configuration of uploadify. But that gave me a trouble, I have posted the issue in my original question. To solve the issue I have declared three <code>input[type=button]</code>. two of the are ordinary HTML button and the last one is <code>&lt;h:commandButton/&gt;</code>. I have set the visibility of this <code>&lt;h:commandButton/&gt;</code> to false and have used a dummy button which will initiate the file upload. When the upload finishes I have programmatically generated the <code>click</code> of ``<code>. Also I have shown a dummy button which don't have any click event associated with it; this the fail safe if, someone clicks on the Upload button twice during the upload is taking place then the the aforementioned click event fire will work unexpectedly. That why I am showing and hiding the buttons. Here is the completed</code>.jspx` pag:</p> <pre><code>&lt;?xml version='1.0' encoding='utf-8'?&gt; &lt;jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" version="2.1" xmlns:f="http://java.sun.com/jsf/core" xmlns:h="http://java.sun.com/jsf/html"&gt; &lt;jsp:output omit-xml-declaration="true" doctype-root-element="HTML" doctype-system="http://www.w3.org/TR/html4/loose.dtd" doctype-public="-//W3C//DTD HTML 4.01 Transitional//EN"/&gt; &lt;jsp:directive.page contentType="text/html;charset=utf-8"/&gt; &lt;f:view&gt; &lt;html&gt; &lt;head&gt; &lt;meta http-equiv="Content-Type" content="text/html; charset=utf-8"/&gt; &lt;script src="js/jquery-1.8.3.min.js" type="text/javascript"&gt;&lt;/script&gt; &lt;script src="uploadify/jquery.uploadify.js" type="text/javascript"&gt;&lt;/script&gt; &lt;link rel="stylesheet" media="screen" href="uploadify/uploadify.css" type="text/css"/&gt; &lt;script type="text/javascript"&gt; $(function() { $('#uploadify').uploadify({ 'auto': false, 'buttonText' : 'Browse', 'fileSizeLimit': 0, 'swf': 'uploadify/uploadify.swf', 'uploader': '${pageContext.request.contextPath}/uploadservlet?key=&lt;h:outputText value="#{uploadBean.key}" /&gt;', 'onQueueComplete' : function(queueData) { $('.checkIn').click(); } }); $('input[name=actualCheckIn]').on('click', function(event){ event.stopPropagation(); $(this).hide(); $('input[name=fakeCheckIn]').show(); $('#uploadify').uploadify('upload','*'); return false; }); }); var upload = function() { } &lt;/script&gt; &lt;title&gt;Upload&lt;/title&gt; &lt;/head&gt; &lt;body&gt; &lt;h:form enctype="multipart/form-data"&gt; &lt;input id="uploadify" type="file"/&gt; &lt;h:commandButton value="Check In" action="#{uploadBean.upload}" styleClass="checkIn" style="display: none"/&gt; &lt;input type="button" value="Check In" name="actualCheckIn"/&gt; &lt;input type="button" value="Check In" onclick="return false;" name="fakeCheckIn" style="display: none"/&gt; &lt;/h:form&gt; &lt;/body&gt; &lt;/html&gt; &lt;/f:view&gt; &lt;/jsp:root&gt; </code></pre> <p>By this whay, when the uplaodify finishes it's upload to the servlet the acution JSF's is fired.</p> <h2>Managed Bean</h2> <p>The managed bean has the scoped <code>Session</code> and here is the code of it:</p> <pre><code>package com.mhis.massupload.bean; import com.mhis.massupload.dto.DocInfo; import java.io.Serializable; import java.util.ArrayList; import java.util.List; import java.util.UUID; import java.util.logging.Level; import java.util.logging.Logger; import javax.faces.context.FacesContext; import javax.servlet.ServletContext; import oracle.stellent.ridc.IdcClientException; import org.apache.commons.fileupload.FileItem; import org.apache.commons.lang3.StringUtils; public class UploadBean implements Serializable { @SuppressWarnings("compatibility:-930710930183135088") private static final long serialVersionUID = -491462816764274947L; private transient Logger log = Logger.getLogger(getClass().getName()); private String key; private transient Service service; public UploadBean() throws IdcClientException { init(); } private void init() throws IdcClientException { key = UUID.randomUUID().toString(); } public String upload() { List&lt;FileItem&gt; fileFields = (List&lt;FileItem&gt;) FacesContext.getCurrentInstance().getExternalContext().getApplicationMap().remove(key); List&lt;DocInfo&gt; docInfos = new ArrayList&lt;DocInfo&gt;(); if (fileFields != null) { for (FileItem fileField : fileFields) { if(StringUtils.isNotBlank(fileField.getName())) { try { System.out.println("Check in: " + fileField.getName()); } catch (Exception e) { log.log(Level.SEVERE, e.getMessage()); } } } } FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put("docInfos", docInfos); return "report"; } public void setKey(String key) { this.key = key; } public String getKey() { return key; } } </code></pre> <p>This worked like charm. </p> <p>Hope it would be helpful.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload