Search code examples
javafilefilepathserversocket

How do i find a filepath given only the name of the file?


I am currently working on transferring a file from a server to a client via tcp connection. The file exists somewhere within a sharedroot directory of the server. This is the sample code of my upload method for server upload to client.

public void upload(String filename, DataOutputStream out) throws IOException {
        File fname = null;
        if (filename.contains(sharedroot)) {   //this is if the client provides a proper filepath with the filename
            fname = new File(filename);
        }else {      //if client only provides a filename without path
            fname = new File(filename);  
//"..\\..\\"+   //i was working around with this, but somehow just making the file whether or not it contains the sharedroot seems to give me the "best" output so far...
        }
        
        System.out.println(fname.getCanonicalPath());
        
        if (fname.isDirectory()) {
            System.out.println("File is a directory");
            String quit = "404 not found";
            sendOut(quit, out);
            return;
        }
        
        String path = fname.getAbsolutePath();
        System.out.println(path);
        
        
        if (fname.isFile()) {
            String canonpath = fname.getCanonicalPath();
            if (canonpath.contains(sharedroot)) {
                try {
                    FileInputStream in = new FileInputStream(fname);

                    byte[] buffer = new byte[1024];

                    out.writeInt(fname.getName().length());
                    out.write(fname.getName().getBytes(), 0, fname.getName().length()); // writes file name only, not
                                                                                        // including the path

                    long size = fname.length();
                    out.writeLong(size);

                    while (size > 0) {
                        int len = in.read(buffer, 0, buffer.length);
                        out.write(buffer, 0, len);
                        size -= len;
                    }
                } catch (Exception e) {
                    System.out.println("Error occurred in uploading file to client. Please try again");
                }
            }else {
                System.out.println("File not in shared directory");
                String quit = "404 not found";
                sendOut(quit, out);
            }
        }else {
            System.out.println("File not exists");
            String quit = "404 not found";
            sendOut(quit, out);
        }
    }

The output given by getCanonicalPath() and getAbsolutePath() as seen below is wrong because it is checking inside the directory of my eclipse and not the sharedroot directory. How can I get the filepath of the file so that i can compare it to my sharedroot and ensure it exists within the sharedroot? The sharedroot would be for example: D:\seant\2uniFiles\1. FINE2005 Year 3

D:\seant\eclipse-workspace\DCN3005\Lecture 1 Exercise.pdf

D:\seant\eclipse-workspace\DCN3005\Lecture 1 Exercise.pdf

File not exists


Solution

  • Your creation of File does not specify a dedicated directory. There are two constructors requiring a (root) directory and a file name – one as File itself, the other as String. I assume one of your paths is relative but your else-branch creates the file the same way as the full qualified path. You should pass the sharedRoot instead as first parameter and the fileName as second.

    File fname = null;
    // sharedRoot is more like a constant and startsWith
    // avoids reading somewhere else that looks similar
    if (filename.startsWith(sharedRoot)) {   
      fname = new File(filename);
    } else {      
      fname = new File(sharedRoot, filename);
    }
    

    In all other cases relative paths are relative to the root directory of the VM process – and I mean process. If for example a user starts this in the user's HOME directory it'll be relative to this. If an operating system task starts the VM it'll be relative to the OS process' root – which might be a Unix cron job or a Windows scheduling thing.

    Maybe you introduce a sort of configuration of sharedRoot so you don't need to recompile if this changes in the future.