使用PrimeFaces 4.0和google app引擎上的jsf 2.2上传文件

时间:2014-01-28 13:27:56

标签: google-app-engine jsf jsf-2 primefaces

我正在使用: -primefaces 4.0 -jsf mojarra 2.2 -google应用程序引擎(servlet api 2.5)  而这个解决方案(Getting primefaces p:fileUpload to work under google appengine)对我没有帮助,因为我的primefaces版本更高。当我在下面用p:commandButton:

使用我的表单时有异常
java.lang.NoSuchMethodError: javax.servlet.http.HttpServletRequest.getPart(Ljava/lang/String;)Ljavax/servlet/http/Part;
at org.primefaces.component.fileupload.NativeFileUploadDecoder.decodeAdvanced(NativeFileUploadDecoder.java:60)
at org.primefaces.component.fileupload.NativeFileUploadDecoder.decode(NativeFileUploadDecoder.java:37)
at org.primefaces.component.fileupload.FileUploadRenderer.decode(FileUploadRenderer.java:44)
at javax.faces.component.UIComponentBase.decode(UIComponentBase.java:831)
at javax.faces.component.UIInput.decode(UIInput.java:771)
at javax.faces.component.UIComponentBase.processDecodes(UIComponentBase.java:1225)
at javax.faces.component.UIInput.processDecodes(UIInput.java:676)
at javax.faces.component.UIForm.processDecodes(UIForm.java:225)
at javax.faces.component.UIComponentBase.processDecodes(UIComponentBase.java:1220)
at javax.faces.component.UIComponentBase.processDecodes(UIComponentBase.java:1220)
at javax.faces.component.UIViewRoot.processDecodes(UIViewRoot.java:929)
at com.sun.faces.lifecycle.ApplyRequestValuesPhase.execute(ApplyRequestValuesPhase.java:78)
at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:198)
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:646)
....

这是因为谷歌不支持servlet api 3.0。我现在真的找不到解决方案。运行primefaces 3.5不是一个选项,因为该项目使用JSF 2.2并且2.2与primefaces 3.5不兼容。

此主题的一个可用评论:How to use PrimeFaces p:fileUpload? Listener method is never invoked or UploadedFile is null

  

更新:自PrimeFaces 4.x以来,当与JSF 2.2和Servlet 3.0结合使用时,不再需要过滤器。将使用Servlet 3.0 / JSF 2.2本机API代替Apache Commons FileUpload。但是其他规则仍然适用,并且可能的原因可以划分#1和#2。

我的表格:

<h:form enctype="multipart/form-data">
<p:fileUpload id="filePhoto" fileUploadListener="#{atlasCasesMB.handleFileUpload}" mode="advanced" dragDropSupport="false"  
    update=":messages" sizeLimit="614400" fileLimit="3" allowTypes="/(\.|\/)(gif|jpe?g|png)$/" />
</h:form>

在这种形式下,不会调用fileUploadListener。

我尝试使用此主题的解决方案:Getting primefaces p:fileUpload to work under google appengine修改DiskFileItem,但显然这无济于事,因为JSF 2.2使用本机API而不是Apache Commons FileUpload。

    <filter>
    <filter-name>PrimeFaces FileUpload Filter</filter-name>
    <filter-class>org.primefaces.webapp.filter.FileUploadFilter</filter-class>
    <init-param>
        <param-name>thresholdSize</param-name>
        <param-value>2147483647</param-value>
    </init-param>
</filter>
<filter-mapping>
    <filter-name>PrimeFaces FileUpload Filter</filter-name>
<servlet-name>Faces Servlet</servlet-name>
</filter-mapping>

有什么建议吗? (降级primefaces和jsf不是一个选项,因为项目处于最后阶段)

我尝试过的解决方案是强制使用apache使用apache公共文件上传(commons-fileupload-1.3.jar):

<context-param>
  <param-name>primefaces.UPLOADER</param-name>
  <param-value>commons</param-value>
</context-param>

然后我使用了过滤器:

<filter>
    <filter-name>PrimeFaces FileUpload Filter</filter-name>
    <filter-class>org.primefaces.webapp.filter.FileUploadFilter</filter-class>
    <init-param>
        <param-name>thresholdSize</param-name>
        <param-value>2147483647</param-value>
    </init-param>
</filter>
<filter-mapping>
    <filter-name>PrimeFaces FileUpload Filter</filter-name>
<servlet-name>Faces Servlet</servlet-name>
</filter-mapping>

这里重要的是设置thresholdSize这么大,以至于某些apache公共类(我忘了哪个)中的write方法没有被调用。最后从primefaces 4.0源文件中添加过滤器FileUploadFilter:http://www.primefaces.org/downloads.html

我过去常常提到的所有来源:

http://davebarber.blog.com/2010/10/15/jsf-2-0-on-google-app-engine/

PrimeFaces 4.0 FileUpload works with Mojarra 2.2 but not MyFaces 2.2

How to use PrimeFaces p:fileUpload? Listener method is never invoked or UploadedFile is null

Getting primefaces p:fileUpload to work under google appengine

这火了:

java.lang.verifyerror inconsistent stackmap frames at branch target

1 个答案:

答案 0 :(得分:2)

要防止primefaces使用其原生文件上传,请添加以下参数。

<context-param>
  <param-name>primefaces.UPLOADER</param-name>
  <param-value>commons</param-value>
</context-param>

然后我使用了过滤器:

<filter>
    <filter-name>PrimeFaces FileUpload Filter</filter-name>
    <filter-class>org.primefaces.webapp.filter.FileUploadFilter</filter-class>
    <init-param>
        <param-name>thresholdSize</param-name>
        <param-value>2147483647</param-value>
    </init-param>
</filter>
<filter-mapping>
    <filter-name>PrimeFaces FileUpload Filter</filter-name>
<servlet-name>Faces Servlet</servlet-name>
</filter-mapping>

这里重要的是设置thresholdSize这么大,以至于某些apache公共类(我忘了哪个)中的write方法没有被调用。最后从primefaces 4.0修改过滤器FileUploadFilter:

package org.primefaces.webapp.filter;

import java.io.File;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;

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 org.apache.commons.fileupload.FileItemFactory;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.gmr.web.multipart.GFileItemFactory;
import org.primefaces.webapp.MultipartRequest;

public class FileUploadFilter implements Filter {

    private final static Logger logger = Logger.getLogger(FileUploadFilter.class.getName());

    private final static String THRESHOLD_SIZE_PARAM = "thresholdSize";

    private final static String UPLOAD_DIRECTORY_PARAM = "uploadDirectory";

    private String thresholdSize;

    private String uploadDir;

    public void init(FilterConfig filterConfig) throws ServletException {
        thresholdSize = filterConfig.getInitParameter(THRESHOLD_SIZE_PARAM);
        uploadDir = filterConfig.getInitParameter(UPLOAD_DIRECTORY_PARAM);

        logger.warning("init:uploadDir=" + uploadDir + "; thresholdSize=" + thresholdSize);
    }

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest httpServletRequest = (HttpServletRequest) request;
        boolean isMultipart = ServletFileUpload.isMultipartContent(httpServletRequest);

        if (isMultipart) {
                logger.warning("Parsing file upload request");

            // start change
            FileItemFactory diskFileItemFactory = new GFileItemFactory();
            /*
             * if(thresholdSize != null) { diskFileItemFactory.setSizeThreshold(Integer.valueOf(thresholdSize)); } if(uploadDir != null) { diskFileItemFactory.setRepository(new File(uploadDir)); }
             */
            // end change

            ServletFileUpload servletFileUpload = new ServletFileUpload(diskFileItemFactory);
            MultipartRequest multipartRequest = new MultipartRequest(httpServletRequest, servletFileUpload);

            if (logger.isLoggable(Level.FINE))
                logger.fine("File upload request parsed succesfully, continuing with filter chain with a wrapped multipart request");

            filterChain.doFilter(multipartRequest, response);
        } else {
            filterChain.doFilter(request, response);
        }
    }

    public void destroy() {
        if (logger.isLoggable(Level.FINE))
            logger.fine("Destroying FileUploadFilter");
    }

}

形式:

<h:form >
<p:fileUpload id="filePhoto" fileUploadListener="#{atlasCasesMB.handleFileUpload}" mode="advanced" dragDropSupport="false"
                    update=":messages" sizeLimit="614400" fileLimit="3" allowTypes="/(\.|\/)(gif|jpe?g|png)$/" />
                <br />
<p:commandButton value="#{bundle['save']}" actionListener="#{atlasCasesMB.saveCase}"  process="@form" />
</h:form>

文件上传处理程序:

public void handleFileUpload(FileUploadEvent event) {
        log.warning("handleFileUpload(FileUploadEvent event)");
        UploadedFile uploadedFile = event.getFile();
        photosArr.add(uploadedFile.getContents());
        //photos.add(new File(uploadedFile.getFileName()));
        FacesMessage msg = new FacesMessage("Succesful", event.getFile().getFileName() + " is uploaded.");  
        FacesContext.getCurrentInstance().addMessage(null, msg);
    }

字节数组照片列表:

private List<byte[]> photosArr;

库:

  • 公地文件上传-1.3.jar
  • 公地-IO-2.4.jar
  • gmultipart-0.2.jar
  • portlet的2.0.jar
  • primefaces-4.0.jar

DiskFileItem: 注释UID和写入方法

和ViewScoped Bean

========================================

有第二种方法可以做到这一点: 使用多部分请求到球衣:

<p:dialog id="upladPhotoDialog" widgetVar="upladPhotoDlg" header="#{bundle['uploading.photos']}" >
    <form action="rest/case" method="post" enctype="multipart/form-data">
        <p>#{bundle['upload.photo.select.images.to.upload']}</p>
    <br />
    <input id="photo1" type="file" name="photo1" />
    <br />
    <input id="photo2" type="file" name="photo2" />
    <br />
    <input id="photo3" type="file" name="photo3" />
    <br />
    <input id="caseId" type="text" name="caseId" style="display:none" value="#{atlasCasesMB.savedCaseId}" />
    <br />
    <input id="btn-post" class="active btn" type="submit" value="Send" />
</form>

@POST
    @Consumes(MediaType.MULTIPART_FORM_DATA)
    public void insertPhotoForCase (
            @FormDataParam("photo1") InputStream photoIS1,
            @FormDataParam("photo2") InputStream photoIS2,
            @FormDataParam("photo3") InputStream photoIS3,
            @FormDataParam("caseId") String caseId , @Context HttpServletRequest httpRequest , @Context HttpServletResponse httpResponse) {
        try {
            DataService<Case> das = new CaseDataService();
            Case caze = das.find(Integer.parseInt(caseId));
            byte[] photoBytes = IOUtils.toByteArray(photoIS1);
            if(photoBytes.length != 0 ){
                sendPhotoToBlob (createPhoto(caze).getId() ,photoBytes);
            }
            photoBytes = IOUtils.toByteArray(photoIS2);
            if(photoBytes.length != 0 ){
                sendPhotoToBlob (createPhoto(caze).getId() ,photoBytes);
            }
            photoBytes = IOUtils.toByteArray(photoIS3);
            if(photoBytes.length != 0 ){
                sendPhotoToBlob (createPhoto(caze).getId() ,photoBytes);
            }
            //currentResponse.sendRedirect("/atlascases.xhtml");
            _context.getRequestDispatcher("/atlascases.xhtml").forward(httpRequest, httpResponse);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

file:jersey-multipart-config.properties在src文件夹中,文本在里面:

bufferThreshold = -1
web.xml中的

    <servlet>
    <servlet-name>Jersey REST Service</servlet-name>
    <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
    <init-param>
        <param-name>com.sun.jersey.config.property.packages</param-name>
        <param-value>com.smartinteractive.medimaging.service</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>Jersey REST Service</servlet-name>
    <url-pattern>/rest/*</url-pattern>
</servlet-mapping>