3

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?

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
redoff
  • 1,124
  • 11
  • 18
  • Do not do according to those two bullets. Choose a fixed location to upload files instead. – Tiny Dec 30 '14 at 01:23
  • i can't use an upload method, i need only the File Path – redoff Dec 30 '14 at 01:32
  • "*i need only the File Path*". Do you mean to say that you want to get the full path of **the uploaded file(s)** (its physical location on disk)? – Tiny Dec 30 '14 at 01:37
  • yes the physical location. with this path, others users can access to the file. ( all this stuff is in the local network ) – redoff Dec 30 '14 at 01:39
  • Which in turn makes no sense. You should not be interested in getting file's absolute path but its contents. That file path is completely meaningless. Think intuitively twice. You upload file(s) from your local computer (for example), the file is stored on your computer. Hence, the physical path of that file points to the location on your computer which is completely irrelevant when you get the uploaded file(s) on the server. After all, what will you do with that path on the server? Do you expect the same file is stored on the server on the exact same location as it was stored on your machine? – Tiny Dec 30 '14 at 01:46
  • sorry, i don't explain rightly the situation. All the files are stored on the same server (machine on a local network). so it's not a real uploading, it's just, if you want, a pointer to this file. an employer create a file and stored it on the server, but others employees don't knows the location. – redoff Dec 30 '14 at 01:50
  • As far as I concerned, the physical path of the uploaded file(s) cannot be obtained on the server-side (some browsers like Internet Explorer send the full file path but after all, it is considered an odd bahaviour of that browser). Even if you were get a physical path of the uploaded file(s) somehow, what do you want to do with that path? Do you want to insert that full physical path into the database so that the file can just be referenced? – Tiny Dec 30 '14 at 02:00
  • yes, this is exactly what i want. with this reference I want to create a button (Locate the file) and when the user click on, the file or the file's directory will be opened – redoff Dec 30 '14 at 02:08
  • You cannot simply open files and/or directories on web browsers. Files can only be downloaded in the form of binary streams. You might be thinking in a wrong way! – Tiny Dec 30 '14 at 02:16
  • I can't create a java method (managed beans) that opens a specific directory ? – redoff Dec 30 '14 at 02:21
  • "*opens a specific directory?*" No. A directory is available on the server's file system which browser cannot (and must not) remotely open. You can only download contents from the server the usual way we download. The answer to "*why*" is quite intuitive we already discussed it in previous comments. – Tiny Dec 30 '14 at 02:29
  • there is no issue in this situation ? the problem is the file can't be downloaded, because it's on a server and all the employees have an access. So if one of them make a change, he should to upload again this file, but if the file stay in the original location, there is no problem. Any suggestions ? – redoff Dec 30 '14 at 02:37
  • I did not get your last comment. The scenario however, appears to be more about stand-alone/desktop applications rather than web applications. – Tiny Dec 30 '14 at 02:45
  • i think it's too late to change a structure to a desktop application. i'm just reading there is some plugins (for chrome, ff and IE) like hyperlink (chrome) that can open a local directory – redoff Dec 30 '14 at 02:50
  • That might happen, if the client and the server happen to be on the same physical machine or sharing a local network using some tricks which I am unfamiliar with. – Tiny Dec 30 '14 at 02:54
  • this is my case (the same local network). there is any solutions to get the path (location) of file ? – redoff Dec 30 '14 at 02:56
  • As far as I am concerned, the actual physical file path of the uploaded file cannot be obtained on the server (as said earlier, some browsers like Internet Explorer (up to some versions) send the full file path but after all, it is considered to be an odd bahaviour of that browser). I cannot imagine the actual solution without knowing the concrete requirements of your application. Some experienced people may shed/expose more light on this topic :) – Tiny Dec 30 '14 at 03:05
  • the application is a kind of EDM (Electronic Document Management) the goal is to give a user the ability to reference a file with keywords, and from these keywords other users can easily access this file. without this application, users who want access to the file must always look in the server tree (it takes hours) – redoff Dec 30 '14 at 03:18

1 Answers1

4

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.

Community
  • 1
  • 1
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • thank you BalusC, awesome explication and a good tip. with time constraint i think i will use simply "copy, paste", in the next revision of application i will use your issue (maybe back to you ) thank you :) – redoff Dec 30 '14 at 12:51