JSF 1.2之前还可以用MyFaces的组件,2.0还是个新玩意,只能靠自己。
开始的想法是自己做一个上传文件组件,组件中封装<input type="file" />,然后用commons-fileupload解析ServletRequest。
代码
import
org.apache.commons.fileupload.
*
;
import javax.faces.context. * ;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
@FacesComponent( " uploadFile.UIUpload " )
public class UIUpload extends UIInput {
public UIUpload() {
this .setRendererType( null );
}
@Override
public void encodeBegin(FacesContext fc) throws IOException {
ResponseWriter rw = fc.getResponseWriter();
String clientId = this .getClientId(fc);
rw.startElement( " input " , this );
rw.writeAttribute( " type " , " file " , null );
rw.writeAttribute( " name " , clientId + " .file " , null );
rw.endElement( " input " );
}
@Override
public void decode(FacesContext fc) {
ExternalContext external = fc.getExternalContext();
HttpServletRequest request = (HttpServletRequest) external.getRequest();
String clientId = getClientId(fc);
if (ServletFileUpload.isMultipartContent(request)) {
FileItemFactory factory = new DiskFileItemFactory();
ServletFileUpload upload = new ServletFileUpload(factory);
try {
List fileItems = upload.parseRequest(request);
// ......
} catch (FileUploadException ex) {
// ......
}
}
}
}
import javax.faces.context. * ;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
@FacesComponent( " uploadFile.UIUpload " )
public class UIUpload extends UIInput {
public UIUpload() {
this .setRendererType( null );
}
@Override
public void encodeBegin(FacesContext fc) throws IOException {
ResponseWriter rw = fc.getResponseWriter();
String clientId = this .getClientId(fc);
rw.startElement( " input " , this );
rw.writeAttribute( " type " , " file " , null );
rw.writeAttribute( " name " , clientId + " .file " , null );
rw.endElement( " input " );
}
@Override
public void decode(FacesContext fc) {
ExternalContext external = fc.getExternalContext();
HttpServletRequest request = (HttpServletRequest) external.getRequest();
String clientId = getClientId(fc);
if (ServletFileUpload.isMultipartContent(request)) {
FileItemFactory factory = new DiskFileItemFactory();
ServletFileUpload upload = new ServletFileUpload(factory);
try {
List fileItems = upload.parseRequest(request);
// ......
} catch (FileUploadException ex) {
// ......
}
}
}
}
上传文件的form需要有属性enctype="multipart/form-data",就像下面这样。cc:uploadfile就是上面那个上传文件的组件。
<
h:form
enctype
="multipart/form-data"
>
< cc:uploadfile />
< h:commandButton value ="Submit" />
</ h:form >
< cc:uploadfile />
< h:commandButton value ="Submit" />
</ h:form >
可是JSF在生成html时,会向form中加入一些<input type="hidden" />的标签,用来恢复组件树。而enctype="multipart/form-data"的form是没法正常提交这些input的,所以组件的decode方法根本就没法执行。
那么现在唯一可行的方法就是通过system event来处理上传文件。
<
f:event
type
="preRenderView"
listener
="#{bean.getPostFile}"
/>
JSF已经发展到2.0了,连<input type="file" />这样最基本的html标签都没有解决,不能不说是个遗憾。除了这个问题外,2.0的改进还是挺大的,我个人最喜欢两点:一是支持get的form和url传值;二是el 2.2的method支持参数。希望Trinidad 2.0和对应的ADF不要让我等太久。