2011-06-18 50 views
1

我想从客户端上传图像到服务器。我已经设法使用像primefaces这样的小工具来做到这一点。但这一次,我想尝试自己做,我在网上找到了关于如何做的信息,但我有点卡住了。 我目前的问题是浏览器对我说,我为上传所创建的标签没有绑定。我想了解,为什么应用程序没有找到它,我应该如何解决它。试图创建我自己的图像上传(JSF)

我会贴上我所做的到现在为止,所以你能不能帮我找到的错误:

1.添加的commons-文件上传-1.2.1.jar和commons-IO-1.4.jar到lib文件夹(自动加入到classpath)

enter image description here

2.Created的XML是西港岛线做标记库可用(这是摆内部WEB-INF文件夹)

<?xml version="1.0" encoding="UTF-8"?> 
<facelet-taglib version="2.0" 
    xmlns="http://java.sun.com/xml/ns/javaee" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
    http://java.sun.com/xml/ns/javaee/web-facelettaglibrary_2_0.xsd"> 
    <namespace>http://corejsf.com</namespace> 
    <tag> 
     <tag-name>upload</tag-name> 
     <component> 
     <component-type>javax.faces.Input</component-type> 
     <renderer-type>com.corejsf.Upload</renderer-type> 
     </component> 
    </tag> 
</facelet-taglib> 

3.创建一个用于执行标签的包并放入一个名为com.corejsf的新包中;

enter image description here

这里是源:

package com.corejsf; 

import java.io.File; 
import java.io.IOException; 
import java.io.InputStream; 
import java.io.UnsupportedEncodingException; 
import javax.el.ValueExpression; 
import javax.faces.FacesException; 
import javax.faces.component.EditableValueHolder; 
import javax.faces.component.UIComponent; 
import javax.faces.context.ExternalContext; 
import javax.faces.context.FacesContext; 
import javax.faces.context.ResponseWriter; 
import javax.faces.render.FacesRenderer; 
import javax.faces.render.Renderer; 
import javax.servlet.ServletContext; 
import javax.servlet.http.HttpServletRequest; 
import org.apache.commons.fileupload.FileItem; 

@FacesRenderer(componentFamily="javax.faces.Input", 
    rendererType="com.corejsf.Upload") 
public class UploadRenderer extends Renderer { 
    public void encodeBegin(FacesContext context, UIComponent component) 
     throws IOException { 
     if (!component.isRendered()) return; 
     ResponseWriter writer = context.getResponseWriter(); 

     String clientId = component.getClientId(context); 

     writer.startElement("input", component); 
     writer.writeAttribute("type", "file", "type"); 
     writer.writeAttribute("name", clientId, "clientId"); 
     writer.endElement("input"); 
     writer.flush(); 
    } 

    public void decode(FacesContext context, UIComponent component) { 
     ExternalContext external = context.getExternalContext(); 
     HttpServletRequest request = (HttpServletRequest) external.getRequest(); 
     String clientId = component.getClientId(context); 
     FileItem item = (FileItem) request.getAttribute(clientId); 

     Object newValue; 
     ValueExpression valueExpr = component.getValueExpression("value"); 
     if (valueExpr != null) { 
     Class<?> valueType = valueExpr.getType(context.getELContext()); 
     if (valueType == byte[].class) { 
      newValue = item.get(); 
     } 
     else if (valueType == InputStream.class) { 
      try { 
       newValue = item.getInputStream(); 
      } catch (IOException ex) { 
       throw new FacesException(ex); 
      } 
     } 
     else { 
      String encoding = request.getCharacterEncoding(); 
      if (encoding != null) 
       try { 
        newValue = item.getString(encoding); 
       } catch (UnsupportedEncodingException ex) { 
        newValue = item.getString(); 
       } 
      else 
       newValue = item.getString(); 
     } 
     ((EditableValueHolder) component).setSubmittedValue(newValue); 
     ((EditableValueHolder) component).setValid(true); 
     } 

     Object target = component.getAttributes().get("target"); 

     if (target != null) { 
     File file; 
     if (target instanceof File) 
      file = (File) target; 
     else { 
      ServletContext servletContext 
       = (ServletContext) external.getContext(); 
      String realPath = servletContext.getRealPath(target.toString()); 
      file = new File(realPath); 
     } 

     try { // ugh--write is declared with "throws Exception" 
      item.write(file); 
     } catch (Exception ex) { 
      throw new FacesException(ex); 
     } 
     } 
    } 
} 

4.然后我添加Servlet过滤器,以区分拦截请求并把它放在同一个包定制标记实施

enter image description here

这是它的源:

package com.corejsf; 

import java.io.File; 
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.FileUploadException; 
import org.apache.commons.fileupload.disk.DiskFileItemFactory; 
import org.apache.commons.fileupload.servlet.ServletFileUpload; 

public class UploadFilter implements Filter { 
    private int sizeThreshold = -1; 
    private String repositoryPath; 

    public void init(FilterConfig config) throws ServletException { 
     repositoryPath = config.getInitParameter(
     "com.corejsf.UploadFilter.repositoryPath"); 
     try { 
     String paramValue = config.getInitParameter(
      "com.corejsf.UploadFilter.sizeThreshold"); 
     if (paramValue != null) 
      sizeThreshold = Integer.parseInt(paramValue); 
     } 
     catch (NumberFormatException ex) { 
     ServletException servletEx = new ServletException(); 
     servletEx.initCause(ex); 
     throw servletEx; 
     } 
    } 

    public void destroy() { 
    } 

    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; 
     } 

     DiskFileItemFactory factory = new DiskFileItemFactory(); 
     if (sizeThreshold >= 0) 
     factory.setSizeThreshold(sizeThreshold); 
     if (repositoryPath != null) 
     factory.setRepository(new File(repositoryPath)); 
     ServletFileUpload upload = new ServletFileUpload(factory); 

     try { 
     @SuppressWarnings("unchecked") List<FileItem> items 
      = (List<FileItem>) upload.parseRequest(httpRequest); 
     final Map<String, String[]> map = new HashMap<String, String[]>(); 
     for (FileItem item : items) { 
      String str = item.getString(); 
      if (item.isFormField()) 
       map.put(item.getFieldName(), new String[] { str }); 
      else 
       httpRequest.setAttribute(item.getFieldName(), item); 
     } 

     chain.doFilter(new 
      HttpServletRequestWrapper(httpRequest) { 
       public Map<String, String[]> getParameterMap() { 
        return map; 
       }     
       // busywork follows ... should have been part of the wrapper 
       public String[] getParameterValues(String name) { 
        Map<String, String[]> map = getParameterMap(); 
        return (String[]) map.get(name); 
       } 
       public String getParameter(String name) { 
        String[] params = getParameterValues(name); 
        if (params == null) return null; 
        return params[0]; 
       } 
       public Enumeration<String> getParameterNames() { 
        Map<String, String[]> map = getParameterMap(); 
        return Collections.enumeration(map.keySet()); 
       } 
      }, response); 
     } catch (FileUploadException ex) { 
     ServletException servletEx = new ServletException(); 
     servletEx.initCause(ex); 
     throw servletEx; 
     }  
    } 
} 

5.Then我注册在web.xml的过滤器。 (我想用一个注解,但是我不知道怎么回事,不知道someon我怎么能做到这一点与注释?) 还增加了corejsf.taglib.xml

<!-- NEEDED FOR FILE UPLOAD --> 
<filter> 
     <filter-name>Upload Filter</filter-name> 
     <filter-class>com.corejsf.UploadFilter</filter-class> 
     <init-param> 
     <param-name>sizeThreshold</param-name> 
     <param-value>1024</param-value> 
     </init-param> 
</filter> 

    <filter-mapping> 
     <filter-name>Upload Filter</filter-name> 
     <url-pattern>/faces/upload/*</url-pattern> 
    </filter-mapping> 

    <context-param> 
     <param-name>javax.faces.PROJECT_STAGE</param-name> 
     <param-value>Development</param-value> 
    </context-param> 
    <context-param> 
     <param-name>facelets.LIBRARIES</param-name> 
     <param-value>/WEB-INF/corejsf.taglib.xml</param-value> 
    </context-param> 

6.On我WebContent文件夹,我创建了一个子文件夹名为上传(上传的文件的目的地)

enter image description here

7.Inside一个JSF页面我用上传的标签并提交,还可以使用托管Bean方法来创建文件na MES:

.... 

<corejsf:upload target="upload/#{placeAddController.prepareUniqueIdentifier}" /> 

.... 

<h:commandButton value="Dalje" style=" font-weight: bold; font-size:150%; action="/submittedImage" /> 

和Java managedbean:

@ManagedBean 
@RequestScoped 
public class PlaceAddControler { 
… 
public String prepareUniqueIdentifier() { 
     return UUID.randomUUID().toString()+"png"; 
    } 

我看到导航到其中添加新的标签页时,该错误是这样的:

javax.faces.view.facelets.FaceletException: Error Parsing /oglas.xhtml: Error Traced[line: 183] The prefix "corejsf" for element "corejsf:upload" is not bound. 
    at com.sun.faces.facelets.compiler.SAXCompiler.doCompile(SAXCompiler.java:387) 
    at com.sun.faces.facelets.compiler.SAXCompiler.doMetadataCompile(SAXCompiler.java:370) 
    at com.sun.faces.facelets.compiler.Compiler.metadataCompile(Compiler.java:123) 
    at com.sun.faces.facelets.impl.DefaultFaceletFactory.createMetadataFacelet(DefaultFaceletFactory.java:353) 
    at com.sun.faces.facelets.impl.DefaultFaceletFactory.getMetadataFacelet(DefaultFaceletFactory.java:231) 
    at com.sun.faces.facelets.impl.DefaultFaceletFactory.getMetadataFacelet(DefaultFaceletFactory.java:164) 
    at com.sun.faces.application.view.ViewMetadataImpl.createMetadataView(ViewMetadataImpl.java:102) 
    at com.sun.faces.lifecycle.RestoreViewPhase.execute(RestoreViewPhase.java:239) 
    at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101) 
    at com.sun.faces.lifecycle.RestoreViewPhase.doPhase(RestoreViewPhase.java:110) 
    at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:118) 
    at javax.faces.webapp.FacesServlet.service(FacesServlet.java:312) 
    at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1523) 
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:279) 
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:188) 
    at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:641) 
    at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:97) 
    at com.sun.enterprise.web.PESessionLockingStandardPipeline.invoke(PESessionLockingStandardPipeline.java:85) 
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:185) 
    at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:325) 
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:226) 
    at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:165) 
    at com.sun.grizzly.http.ProcessorTask.invokeAdapter(ProcessorTask.java:791) 
    at com.sun.grizzly.http.ProcessorTask.doProcess(ProcessorTask.java:693) 
    at com.sun.grizzly.http.ProcessorTask.process(ProcessorTask.java:954) 
    at com.sun.grizzly.http.DefaultProtocolFilter.execute(DefaultProtocolFilter.java:170) 
    at com.sun.grizzly.DefaultProtocolChain.executeProtocolFilter(DefaultProtocolChain.java:135) 
    at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:102) 
    at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:88) 
    at com.sun.grizzly.http.HttpProtocolChain.execute(HttpProtocolChain.java:76) 
    at com.sun.grizzly.ProtocolChainContextTask.doCall(ProtocolChainContextTask.java:53) 
    at com.sun.grizzly.SelectionKeyContextTask.call(SelectionKeyContextTask.java:57) 
    at com.sun.grizzly.ContextTask.run(ContextTask.java:69) 
    at com.sun.grizzly.util.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:330) 
    at com.sun.grizzly.util.AbstractThreadPool$Worker.run(AbstractThreadPool.java:309) 
    at java.lang.Thread.run(Thread.java:662) 

- 什么我错过了?

- 我还需要做什么才能将文件从客户端传输到具有唯一文件名的服务器文件系统,位于上传文件夹内。

我最终的目标不是将这些图像添加到数据库中,而是将它们留在文件系统中。

我希望有人能帮助我。

UPDATE

我加入的xmlns,到我的网页和固定异常:

的xmlns:corejsf = “http://corejsf.com”

但为什么当我点击按钮,文件不上传?

回答

1

如果您还没有,您需要将XML名称空间添加到页面,就像您为Facelets,PrimeFaces等做的一样。这应该解决“前缀未绑定”的错误。

<html xmlns="http://www.w3.org/1999/xhtml" 
    xmlns:h="http://java.sun.com/jsf/html" 
    xmlns:corejsf="http://corejsf.com"> 
+0

是的,我忘了那个。这解决了这个例外。谢谢。我仍然没有看到上传文件夹中的文件,我点击提交后。这是为什么? – sfrj

+0

我无法立即看到。如果您还没有,我会建议您使用调试器。 –

+0

好吧,我会尝试。我已经检查过,并且我的表单使用了:''唯一让我感到厌烦的是如果action =“/ submittedImage”实际上允许表单提交。我如何检查? – sfrj