6

升级到 GlassFish 4 和 JSF 2.2 Primefaces FileUploadEvent 后停止工作。使用 JSF 2.1 可以正常工作。除文件上传外,一切正常。有什么我想念的吗?

    GlassFish 4
    JSF 2.2
    PrimeFaces 3.4.2 and 3.5
    Commons io version: 2.4
    Commons fileupload version: 1.3

控制器端

public void handleFileUpload(FileUploadEvent event) {
    System.out.println("HandleFileUpload");
    byte[] file = event.getFile().getContents();
    newFieldset.setData(file);
    FacesMessage msg = new FacesMessage("Succesful", event.getFile().getFileName() + " is uploaded.");
    FacesContext.getCurrentInstance().addMessage(null, msg);
}

看法

<h:form enctype="multipart/form-data">
            <p:fieldset legend="Create new feed" toggleable="true" collapsed="true" >
                <p:fileUpload fileUploadListener="#{adminHomeController.handleFileUpload}" style="margin-top: 20px;"
                              mode="advanced" 
                              update="messages"
                              sizeLimit="1000000" 
                              multiple="false" 
                              allowTypes="/(\.|\/)(gif|jpe?g|png)$/"/>
                <p:inputText label="Baslik" style="margin-top: 20px;" required="true" value="#{adminHomeController.newFieldset.legend}"  /> 
                <p:editor style="margin-top: 20px;"
                          value="#{adminHomeController.newFieldset.content}" />
                <p:commandButton style="margin-top: 20px;" value="#{msg['common.save']}" update="messages" icon="ui-icon-disk" actionListener="#{adminHomeController.saveFieldset()}"/>
            </p:fieldset>
            <p:growl id="messages" showDetail="true"/>
        </h:form>
4

6 回答 6

6

我终于能够弄清楚了。Commons-fileuploads 方法parseRequest(httpServletRequest)尝试读取请求的 inputStream。由于容器已经读取它,它是空的。那么可以做些什么来解决这个问题呢?答案比我最初想象的要复杂一些。首先,您需要自己的 FileUploadFilter,如下所示:

public class FileUploadFilter implements Filter 
{
private final static Logger LOGGER = LoggerFactory.getLogger(FileUploadFilter.class);

/*
 * (non-Javadoc)
 * 
 * @see javax.servlet.Filter#init(javax.servlet.FilterConfig)
 */
@Override
public void init(FilterConfig filterConfig) throws ServletException 
{
}

/*
 * (non-Javadoc)
 * 
 * @see javax.servlet.Filter#doFilter(javax.servlet.ServletRequest,
 * javax.servlet.ServletResponse, javax.servlet.FilterChain)
 */
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException 
{
    HttpServletRequest httpServletRequest = (HttpServletRequest) request;
    boolean isMultipart = (httpServletRequest.getContentType() == null) ? false : httpServletRequest.getContentType().toLowerCase().startsWith("multipart/");

    if (isMultipart) 
    {
        MultipartRequest multipartRequest = new MultipartRequest(httpServletRequest);

        LOGGER.info("File upload request parsed succesfully, continuing with filter chain with a wrapped multipart request");

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

/*
 * (non-Javadoc)
 * 
 * @see javax.servlet.Filter#destroy()
 */
@Override
public void destroy() 
{
    LOGGER.info("Destroying UploadFilter");
}

下一步:在您的 web.xml 中注册此过滤器并删除/替换 Primefaces 过滤器。这应该看起来像这样:

  <filter>
    <filter-name>FileUpload Filter</filter-name>
    <filter-class><YourPackage>.FileUploadFilter</filter-class>
  </filter>
  <filter-mapping>
     <filter-name>FileUpload Filter</filter-name>
     <servlet-name>Faces Servlet</servlet-name>
  </filter-mapping>

不幸的是,事实并非如此。您将需要自己的 MultipartRequest,因为您必须自己组装 FileItems 列表。但是停下来。我们必须使用与 FileItem 不兼容的 javax.servlet.Part 类。所以我写了一个新的类来连接这两者。你可以在这里找到这个类:http: //pastebin.com/JcfAYjey

最后一块拼图是前面提到的 MultipartRequest,它链接了 PartItem 和 FileUploadFilter。我从 Primefaces-Repository 中学习了这门课,并根据需要进行了更改(请参阅http://pastebin.com/Vc5h2rmJ)。区别在于第 47 行和第 57 行。

那么您需要做什么: 1. 创建三个类 FileUploadFilter、MultipartRequest 和 PartItem 2. 在您的 web.xml 中注册 FileUploadFilter 3. 享受吧!

请注意:这并不是一个解决所有问题的解决方案,而只是一个您可以在进一步实施中采取的方向。例如 MultipartRequest 仅适用于具有 content-type 的部分image/*。您可能需要更改此设置。

随意更改代码;)希望它有所帮助!

编辑:我忘了提到一个重要的步骤。您还需要自己的 FileIUploadRenderer。实现的 Primefaces 使用instanceof检查来查找 MultipartRequest。由于您现在使用的是不同的,因此必须更改导入。其余的课程可以保持不变(http://pastebin.com/rDUkPqf6)。不要忘记在 faces-config.xml 中注册它:

<render-kit>
   <renderer>
        <component-family>org.primefaces.component</component-family>
        <renderer-type>org.primefaces.component.FileUploadRenderer</renderer-type>
        <renderer-class><YourPackage>.FileUploadRenderer</renderer-class>
     </renderer>
</render-kit>
于 2013-06-28T11:44:48.497 回答
4

答案在于UploadFile getInputstream()方法。不要依赖getContents()方法。这是我的简单解决方案,它与 glassfish 4 中的以下依赖项一起使用

  • Primefaces 4.0.RC1
  • jsf 2.2
  • 公共文件上传 1.3

    private byte[] getFileContents(InputStream in) {
        byte[] bytes = null;
        try {            
            // write the inputStream to a FileOutputStream            
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            int read = 0;
             bytes = new byte[1024];
    
            while ((read = in.read(bytes)) != -1) {
                bos.write(bytes, 0, read);
            }
            bytes = bos.toByteArray();
            in.close();
            in = null;
            bos.flush();
            bos.close();
            bos = null;
            logger.debug("New file created!");
        } catch (IOException e) {
            System.out.println(e.getMessage());
        }
        return bytes;
    }
    getFileContents(getFile().getInputstream()); 
    
于 2013-09-25T09:26:36.617 回答
3

尝试删除beans.xml(CDI 配置文件)并使用 JSF bean。

于 2013-06-21T11:54:02.153 回答
2

我在 PrimeFaces 博客上看到完整的 JSF 2.2 支持将从 4.0 版开始。

于 2013-09-13T08:33:51.790 回答
1

我认为这是一个公共文件上传问题。当我通过代码进行调试时,PrimeFaces 的 UploadFilter 正确触发了 commons-fileupload 的 FileUploadBase.parseRequest 方法(当我使用 GlassFish 3.1.22 或 GlassFish 4 时,流程相同),但对 FileItemIterator.hasNext 的检查返回 false。

于 2013-06-23T15:54:03.057 回答
1

请参阅3.5 缺少依赖项 - 所以不会启动

于 2013-06-20T18:29:39.903 回答