使用p:fileUpload将完整的客户端文件路径发送到服务器端

时间:2014-12-30 01:14:17

标签: jsf file-upload primefaces

我正在使用:

  • PrimeFaces 5.0
  • GlassFish 4.1
  • Netbeans 8.0.2

我的情况:我有一个Intranet Web应用程序,我想让客户端浏览Intranet网络磁盘文件系统,并将完整的客户端文件路径发送到服务器端。换句话说,我不需要文件内容,只需要完整的文件路径,就像在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);
}

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

  

C:\用户\ XXX \应用程序数据\漫游\的NetBeans \ 8.0.2 \配置\ GF_4.1 \ domain1的\配置\ file.txt的

并且realPath打印以下内容:

  

C:\用户\ XXX \文件\的NetBeansProjects \ PROJECT \ DIST \ gfdeploy \ PROJECT \ PROJECT-war_war \

但是,我期待看到

  

\\ MACHINE \文档\ file.txt的

我怎样才能做到这一点?

1 个答案:

答案 0 :(得分:4)

你基本上是在寻找解决方案的错误方向。而且,你以错误的方式看待JSF / PrimeFaces。 JSF就是这个问题的上下文,只是一个HTML代码生成器。

HTML不支持将完整的客户端文件路径发送到服务器端。确实,较旧的Internet Explorer版本存在一个尴尬的安全漏洞,即沿文件名发送完整的客户端文件路径。但是,这不是HTML的强制要求。 <input type="file">的唯一目的是将文件内容从客户端发送到服务器which you're supposed to read via getInputStream() and save on a fixed location yourself。文件名只是附加的元数据。这通常从不用于将文件保存在服务器中,以避免被其他上传文件覆盖,同时使用相同的文件名。文件名最多用作服务器端最终文件名的前缀,或者仅记住以便在&#34;另存为&#34;中重新显示。在下载过程中。但那就是它。

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

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

.. the getFileName() only returns the file name, not the file pathnew File(...)构造函数将解释相对于&#34;当前工作目录&#34;的文件名,即在JVM(在您的情况下,服务器)启动时打开的目录。基本上,您正在尝试查找不存在的文件。实际文件存储在其他位置,通常位于OS无法控制的临时文件位置。但是,这也不是您正在寻找的。

在这里,

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

.. the getRealPath() only converts the webcontent-relative path to absolute disk file system path。换句话说,它为您提供了deploy文件夹的路径,其中存储了扩展WAR文件的所有内容。通常它是XHTML / JS / CSS文件等。这绝对不是你想要的。而且,getRealPath()没有单一明智的现实世界用例。你绝对应该避免使用它。

您需要以与HTML不同的方向寻找解决方案。您需要一个能够抓取完整客户端文件路径然后将其发送到服务器端的客户端应用程序。 HTML无法做到(甚至不是HTML5)。 CSS无法做到。 JS无法做到。但是Java可以做到。您可以使用Swing JFileChooser浏览并选择实际的File。您只需要在客户端而不是服务器端执行它。您可以使用an Applet进行此操作,您可以轻松地将其嵌入任何网页,甚至是JSF页面;你知道,它只是一个HTML代码生成器。

基本上:

  1. 在小程序中,通过JFileChooser抓取完整文件路径。

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

    其他优点是,您可以使用FileSystemView将其限制为某些(网络)驱动器或文件夹,以便最终用户不会意外选择完全不相关的驱动器/文件夹。

  2. 通过URLConnection将完整文件路径作为查询参数发送到服务器端。

    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. 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. 在JSF页面中嵌入applet时,不要忘记将会话ID作为applet参数传递。

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

    这样,servlet可以访问与JSF页面完全相同的HTTP会话,然后您可以在它们之间共享/通信数据。