使用p:fileUpload发送完整的客户端文件路径到服务器端 [英] Send full client side file path to server side using p:fileUpload

查看:446
本文介绍了使用p:fileUpload发送完整的客户端文件路径到服务器端的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用的是:


  • PrimeFaces 5.0

  • GlassFish 4.1

  • Netbeans 8.0.2



我的情况是:我有一个Intranet Web应用程序,客户端浏览内网网络磁盘文件系统,并将完整的客户端文件路径发送到服务器端。换句话说,我不需要文件内容,而只需要完整的文件路径,就像它在Intranet网络中一样。



我试过使用< p:fileUpload> 为此:

  public void handleFileUpload(FileUploadEvent event)throws IOException {
UploadedFile uploadedFile = event.getFile();
InputStream inputStream = uploadedFile.getInputstream();

File file = new File(uploadedFile.getFileName());
System.out.println(file.getAbsolutePath());

String realPath = FacesContext.getCurrentInstance()。getExternalContext()。getRealPath(/);
System.out.println(realPath);



$ b $ file.getAbsolutePath()打印以下内容:


\ Users \XXX\AppData\Roaming\NetBeans\8.0。 2 \config\GF_4.1\domain1\config\file.txt

而且, realPath 打印以下内容:


C:\ Users \XXX\Documents\NetBeansProjects \PROJECT\dist\gfdeploy\PROJECT\PROJECT-war_war\


不过,我期待看到
$ b


\\MACHINE\Documents\file.txt


我怎样才能做到这一点?

解决方案

解。而且,你正在以一种错误的方式看待JSF / PrimeFaces。 JSF在这个问题的上下文中只是一个HTML代码生成器。



HTML不支持将完整的客户端文件路径发送到服务器端。诚然,较早的Internet Explorer版本有一个尴尬的安全漏洞,即完整的客户端文件路径是沿文件名发送的。但是,这不是由HTML强制的。 < input type =file> 的唯一目的是将文件内容从客户端发送到服务器,你应该阅读通过 getInputStream()并保存在一个固定的位置自己。文件名在这里只是额外的元数据。这通常不会原样用于将文件保存在服务器中,以避免被其他上载文件覆盖,而且文件名相同。文件名称最多用作服务器端最终文件名的前缀,或者只能在下载过程中为了在另存为中重新显示而被记住。但是,就是这样。

所有的尝试都失败了,因为这里,

  File file = new File(uploadedFile.getFileName()); 
System.out.println(file.getAbsolutePath());

.. getFileName()只返回文件中的文件路径从-html-input-form-in-firefox-3/3374408#3374408# 名称,而不是文件路径新的File(...)构造函数将解释相对于当前工作目录的文件名,也就是当前JVM所打开的目录情况下,服务器),已启动。基本上,你试图找到一个不存在的文件。实际的文件存储在其他地方,通常在操作系统管理的临时文件位置之外。然而,这也不是你要找的。

在这里,

  String realPath = FacesContext.getCurrentInstance()。getExternalContext()。getRealPath(/); 
System.out.println(realPath);

.. getRealPath()中,只将webcontent相对路径转换为绝对磁盘文件系统路径。换句话说,它为您提供了展开WAR文件所有内容的部署文件夹的路径。通常它是XHTML / JS / CSS文件等等。这也绝对不是你要找的。而且,对于 getRealPath()没有一个明智的真实世界用例。您应该绝对避免使用它。



您需要寻找与HTML不同方向的解决方案。您需要一个客户端应用程序能够抓住完整的客户端文件路径,然后将其发送到服务器端。 HTML不能这样做(即使不是HTML5)。 CSS不能做到这一点。 JS不能做到这一点。但Java可以做到这一点。您可以使用 Swing JFileChooser 文件。您只需要在客户端而不是服务器端执行它。您可以使用一个小程序,然后您可以轻松地嵌入任何网页,甚至一个JSF页面;你知道,这只是一个HTML代码生成器。

基本上:
$ b $ ol

  • 在applet中,通过 JFileChooser 获取完整的文件路径。

      JFileChooser fileChooser = new JFileChooser(); 
    if(fileChooser.showSaveDialog(null)== JFileChooser.APPROVE_OPTION){
    File selectedFile = fileChooser.getSelectedFile();
    字符串selectedFileAbsolutePath = selectedFile.getAbsolutePath();
    // ...
    } else {
    //用户按下取消。



    $ b $ p
    $ b另外一个好处是,你可以使用 FileSystemView 将其限制到特定的(网络)驱动器或文件夹,以便最终用户不会意外地选择完全不相关的驱动器/文件夹。
  • 通过 URLConnection 查询参数到服务器端。

      String url =/ someServletURL?selectedFileAbsolutePath =+ URLDecoder.decode(selectedFileAbsolutePath,UTF-8); 
    URLConnection连接=新的URL(getCodeBase(),url).openConnection();
    connection.setRequestProperty(Cookie,JSESSIONID =+ getParameter(sessionId));
    InputStream response = connection.getInputStream();
    // ...


  • 阅读servlet

      @WebServlet(/ someServletURL)
    public class SomeServlet extends HttpServlet {
    $ b @Override $ b $ public void doGet(HttpServletRequest request,HttpServletResponse resposne)throws ServletException,IOException {
    String selectedFileAbsolutePath = request .getParameter( selectedFileAbsolutePath);
    // ...
    }

    }


  • <

     < p> 

    小程序...>
    < param name =sessionIdvalue =#{session.id}/>
    < / applet>

    通过这种方式,servlet将访问与JSF页面完全相同的HTTP会话,然后您可以在它们之间共享/传递数据。


    I'm using:

    • PrimeFaces 5.0
    • GlassFish 4.1
    • Netbeans 8.0.2

    My case: I have an intranet web application where I'd like to let the client browse the intranet network disk file system and send the full client side file path to the server side. In other words, I do not need the file contents, but only the full file path, as it is in the intranet network.

    I tried using <p:fileUpload> for this:

    public void handleFileUpload(FileUploadEvent event) throws IOException {
        UploadedFile uploadedFile = event.getFile();
        InputStream inputStream = uploadedFile.getInputstream();
    
        File file = new File(uploadedFile.getFileName());
        System.out.println(file.getAbsolutePath());
    
        String realPath = FacesContext.getCurrentInstance().getExternalContext().getRealPath("/");
        System.out.println(realPath);
    }
    

    The file.getAbsolutePath() prints the following:

    C:\Users\XXX\AppData\Roaming\NetBeans\8.0.2\config\GF_4.1\domain1\config\file.txt

    And, the realPath prints the following:

    C:\Users\XXX\Documents\NetBeansProjects\PROJECT\dist\gfdeploy\PROJECT\PROJECT-war_war\

    However, I'm expecting to see

    \\MACHINE\Documents\file.txt

    How can I achieve this?

    解决方案

    You're basically looking in the wrong direction for the solution. And, you're looking at JSF/PrimeFaces in a wrong way. JSF is in the context of this question just a HTML code generator.

    HTML does not support sending full client side file path to the server side. True, older Internet Explorer versions had the awkward security bug that the full client side file path was sent along the file name. But, this is not mandated by HTML. The sole purpose of <input type="file"> is to send the file content from client to server, which you're supposed to read via getInputStream() and save on a fixed location yourself. The filename is here just additional metadata. This is usually never used as-is to save the file in the server, to avoid overwrites by other uploads with coincidentally the same filename. The file name is at most used as prefix of the final file name in the server side, or only remembered in order to be redisplayed in "Save As" during a download. But that's it.

    All your attempts failed because here,

    File file = new File(uploadedFile.getFileName());
    System.out.println(file.getAbsolutePath());
    

    .. the getFileName() only returns the file name, not the file path. The new File(...) constructor will interpret the file name relative to the "current working directory", i.e. the directory which was open at the moment the JVM (in your case, the server), was started. Basically, you're attempting to locate a non-existing file. The actual file is stored elsewhere, usually in the OS-managed temporary file location beyond your control. However, this is also not what you're looking for.

    And here,

    String realPath = FacesContext.getCurrentInstance().getExternalContext().getRealPath("/");
    System.out.println(realPath);
    

    .. the getRealPath() only converts the webcontent-relative path to absolute disk file system path. In other words, it gives you the path to the deploy folder where all contents of the expanded WAR file are stored. Usually it are the XHTML/JS/CSS files and such. This is also definitely not what you're looking for. Moreover, there is no single sensible real world use case for getRealPath(). You should absolutely avoid using it.

    You need to look for the solution in a different direction than HTML. You need a client side application capable of grabbing the full client side file path and then sending it to the server side. HTML can't do it (even not HTML5). CSS can't do it. JS can't do it. But Java can do it. You can use Swing JFileChooser to browse and pick the actual File. You only need to execute it in the client side instead of the server side. You can use an Applet for this which you in turn can easily embed in any webpage, even a JSF page; you know, it's just a HTML code generator.

    Basically:

    1. In applet, grab full file path via JFileChooser.

      JFileChooser fileChooser = new JFileChooser();
      if (fileChooser.showSaveDialog(null) == JFileChooser.APPROVE_OPTION) {
          File selectedFile = fileChooser.getSelectedFile();
          String selectedFileAbsolutePath = selectedFile.getAbsolutePath();
          // ...
      } else {
          // User pressed cancel.
      }
      

      Additional advantage is, you can use FileSystemView to restrict it to certain (network) drives or folders, so that the enduser won't accidentally select completely irrelevant drives/folders.

    2. Send the full file path as query parameter via URLConnection to server side.

      String url = "/someServletURL?selectedFileAbsolutePath=" + URLDecoder.decode(selectedFileAbsolutePath, "UTF-8");
      URLConnection connection = new URL(getCodeBase(), url).openConnection();
      connection.setRequestProperty("Cookie", "JSESSIONID=" + getParameter("sessionId"));
      InputStream response = connection.getInputStream();
      // ...
      

    3. Read it in a servlet.

      @WebServlet("/someServletURL")
      public class SomeServlet extends HttpServlet {
      
          @Override
          public void doGet(HttpServletRequest request, HttpServletResponse resposne) throws ServletException, IOException {
              String selectedFileAbsolutePath = request.getParameter("selectedFileAbsolutePath");
              // ...
          }
      
      }
      

    4. Don't forget to pass session ID as applet parameter when embedding the applet in JSF page.

      <applet ...>
          <param name="sessionId" value="#{session.id}" />
      </applet>
      

      This way the servlet will have access to exactly the same HTTP session as the JSF page, and then you can share/communicate data between them.

    这篇关于使用p:fileUpload发送完整的客户端文件路径到服务器端的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆