【问题标题】:Add a input file with JSF 1.2使用 JSF 1.2 添加输入文件
【发布时间】:2012-12-23 21:26:21
【问题描述】:

我需要以专用于上传文件的形式上传。在我的项目中,我可以使用 JSF 1.2 和 RichFaces 3.3.3,但我不能使用 <rich:fileUpload/>,因为我的客户想要一个简单的输入,就像 <input type="file"/>

如果可以的话,我会使用 Primeface 或 Tomahawk 的文件上传,但我被禁止,我不能使用其他库,我也不能使用 Servlet 3.0 下 Apache 文件上传。我现在能做什么?我见过其他类似的问题,但他们可以使用其他库,我不能,我受到限制......

【问题讨论】:

  • 为什么要投反对票?评论而不是投反对票然后走开 ¬¬
  • 使用 3rd 方控件或库是最简单的。由于这不是一个选项,您将不得不开始阅读 MIME 规范,因为您将要编写 MIME 解析器。
  • @McDowell 是的,我知道这会更简单,我还使用 lib 做了一个版本,但它被拒绝了:/ 我目前正在尝试使用 servlet 接收文件...

标签: jsf file-upload richfaces jsf-1.2


【解决方案1】:

自从我不得不为 JSF 编写 MIME 解析器已经有一段时间了,但这就是我记得的过程。

您需要编写一个解析器来从multi-part/formdata 有效负载中提取数据。有个好overview of multi-part/formdata on the W3 site

您需要决定是否定位:

  • 具有普通表单/控件的非 JSF servlet
  • 带有 JSF 表单和自定义文件上传控件的 JSF servlet

以普通 servlet 为目标

只要上传 POST 操作不需要调用依赖于 JSF 上下文(托管 bean 等)的代码,这将是一种更简单的方法

您的 servlet 解析输入流中的数据并根据需要对其进行操作。

以 JSF 视图/动作为目标

在这里,您需要修饰请求(最好使用HttpServletRequestWrapper)以将解析后的parameters 提供给JSF 框架。这通常在filter 中完成,该filter 从 HTTP 标头中检测帖子类型。在调用任何表单操作之前,需要决定文件数据的存储位置以及如何将该数据公开给托管 bean。

您还需要考虑是否要为文件上传输入类型创建自定义 JSF 控件,或者是否可以使用纯 HTML 元素。

值得检查您无法使用的解析器/控件的功能,以确保您提供简单的功能 - 例如最大有效负载大小,以防止攻击者将千兆字节的数据上传到您的应用程序。

【讨论】:

  • 谢谢,但经过数小时尝试多种上传方式后,我发现了 RichFaces (org.ajax4jsf.request.MultipartRequest) 中包含的 Ajax4J 的多部分实现,所以我不需要自己实现: )
【解决方案2】:

为了用可接受的解决方案解决这个问题,我创建了一个普通表单和一个 servlet,servlet 接收multipart/form-data 请求并使用 RichFaces 3.3.3 中包含的org.ajax4jsf.request.MultipartRequest 来解析接收到的参数和附件,然后我将File 实例保存在会话中,并在 JSF 上下文中恢复它。

xhtml:

<a4j:form >
    <a4j:jsFunction name="finishUpload" 
            action="#{importacaoController.actionUploadArquivoDadosXX}"
            reRender="uploadedFile,globalMensagens" />
    <a4j:jsFunction
        name="tipoNaoSuportado" reRender="globalMensagens" action="#{importacaoController.actionTipoNaoSuportado }"
        />
</a4j:form>
<form target="uploader" id="uploaderForm" action="#{request.contextPath}/MyServlet"
    method="post" enctype="multipart/form-data" style="position: absolute;margin: -210px 0 0 300px;">
    <div class="modulo-6-12">
        <label for="uploadFileField">Anexar arquivo</label><br/>
        <input type="file" id="uploadFileField" name="upload" onchange="jQuery('#uploaderForm').submit();" />
    <br />
    <small><h:outputText id="uploadedFile" value="#{importacaoController.arquivoConfig.name}" /></small>
    </div>
</form>
<iframe id="uploader" width="0" height="0" src="" style="display: none; border: 0; margin:0;padding:0;"></iframe>

Servlet:

public class MyServlet extends HttpServlet {

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String encoding = request.getCharacterEncoding();
        if(encoding == null) request.setCharacterEncoding("UTF-8");
        MultipartRequest mpRequest = new MultipartRequest(request,true,10*1024*1024,"importarXX");
        String field = "upload";
        Object o =mpRequest.getFile(field);
        if(o instanceof File)
        {
            File file = (File)o;
            HttpSession sess = request.getSession();
            String name = mpRequest.getFileName(field);

            Writer w = response.getWriter();
            w.write("<html><head><script>");
            if(!name.endsWith(".xls"))
            {

                w.write("parent.window.tipoNaoSuportado()" +
                        //"alert('Só são permitidos arquivos com extensão .xls');" +
                        "</script></head><body></body></html>");
                w.close();
                file.delete();
                return;
            }

            sess.setAttribute("importarXXFile", o);
            sess.setAttribute("importarXXFileName", name);
            w.write("parent.window.finishUpload();</script></head><body>Sucesso</body></html>");
            w.close();
        }
    }
}

控制器:

public boolean actionUploadArquivoDadosXX(){
    flgTipoNaoSuportado = false;
    HttpSession sess = ((HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest()).getSession();
    File uploadedFile = (File) sess.getAttribute("importarXXFile");
    String uploadedFileName = (String) sess.getAttribute("importarXXFileName");
    boolean ret = false;

    if(uploadedFile != null && uploadedFileName != null){
        BeanArquivoUpload arquivo = new BeanArquivoUpload();
        arquivo.setFile(uploadedFile);
        arquivo.setName(uploadedFileName);
        arquivo.setFileSize(uploadedFile.length());
        setArquivoConfig(arquivo);
        ret = true;
    }
    else
    {
         setArquivoConfig(null);
    }

    sess.removeAttribute("importarXXFile");
    sess.removeAttribute("importarXXFileName");

    return ret;


}

【讨论】:

    【解决方案3】:

    我之前也遇到过同样的问题。我通过在用户单击浏览按钮时打开一个弹出窗口解决了这个问题,这个新的弹出窗口直接链接到一个支持文件上传和下载的 servlet。 上传文件后,servlet 在加载 servlet 主体时调用 window.close() 直接关闭弹出窗口。 以下是所做的更改:

    在提示用户输入文件的 addItem.jsp 中:

    <script type="text/javascript">
           ...
      function newWindow()
      {
        popupWindow = window.open('addItemImage.jsp','name','width=200,height=200');
      }
        ...
     </script>
    
         <f:view>
             <h:form id="search" onsubmit="return validateDetails()">
              ...
    
               <h:panelGroup>
                    <font color="black">Item Image :</font>
               </h:panelGroup>
               <h:panelGroup>
                    <input type="button" value="Upload Image" onClick="newWindow()"/>
               </h:panelGroup>
    
              ...
              </h:form>
          </f:view>
    

    在新打开的弹出窗口中:addItemImage.jsp

    <script type="text/javascript">
        function validate()
        {
            var file = document.getElementById("file").value;
            if(file == null || file == "")
                return true;
            if(file.indexOf(".jpg") == -1 && file.indexOf(".gif")  && file.indexOf(".bmp") == -1 && file.indexOf(".jpeg") == -1) 
            {
                alert("Invalid File Format!! Please upload jpg/bmp/gif");
                return false;
            }
            return true;
        } 
    </script>
    <body>
        <form enctype="multipart/form-data" method="post" action="FileUploaderServler.view" onsubmit="return validate()">
            <input type="file" name="file" id="file" />
            <input type="submit" value="Upload Image">
        </form>
    </body>
    

    这将发布到一个 servlet,然后该 servlet 将呈现图像并将其保存在一个地方。 FileUploaderServlet.java

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException 
        {
            List<FileItem> items = null;
            try 
            {
                 MultipartHTTPServletRequest multipartHTTPServletRequest = new MultipartHTTPServletRequest(Connection.getRequest());
                items = new ServletFileUpload(new DiskFileItemFactory()).parseRequest(multipartHTTPServletRequest);
            } 
            catch (FileUploadException e) 
            {
                e.printStackTrace();
            }
            if(!Util.isNullList(items))
            {
                for (FileItem item : items) 
                {
                    if (!item.isFormField()) 
                    {
                        String itemName = item.getFieldName();
                        InputStream filecontent = null;
    
                        try 
                        {
                            filecontent = item.getInputStream();
                        } 
                        catch (IOException e) 
                        {
                            e.printStackTrace();
                        }
    
                       /* String currDirPath = System.getProperty("user.dir"); // C:\Users\KISHORE\Desktop\eclipse
                        File file = new File(currDirPath+"\\itemImages");*/
                        new File(Constants.ABS_FILE_PATH_TO_IMAGES).mkdir();
                        File fw = new File(Constants.ABS_FILE_PATH_TO_IMAGES+"\\"+Connection.getRequest().getSession().getId()+".jpg"); // E:\Kishore Shopping Cart\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\wtpwebapps\ShoppingCart\WEB-INF\itemImages\EC34EEE58065AD674192D3D57124F07E.jpg
                        fw.delete();
                        fw.createNewFile();
                        try 
                        {
                            item.write(fw);
                        } 
                        catch (Exception e) 
                        {
                            e.printStackTrace();
                        }
                    }
                }
    
            }
    
            PrintWriter out = response.getWriter();
            out.print("<html><title>Add Image to Item</title><body onload='window.close()'>Uploaded Successfully!!</body>");
            System.out.print("</html>");
        }
    

    这个servlet在配置的地方完成保存文件后,会直接关闭之前打开的弹出窗口。

    这样我就可以使用托管bean,jsf 1.2并实现文件上传。 我在stackoverflow上找到了其他方法,但感觉实现起来有点复杂。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-09-23
      • 2011-07-11
      • 1970-01-01
      • 1970-01-01
      • 2011-06-18
      • 2023-03-19
      • 1970-01-01
      • 2015-11-13
      相关资源
      最近更新 更多