34

Java7 ships with a default Path implementation for local files. Is there a Path implementation for URLs?

For example, I should be able to copy a remote resource using the following code:

Path remote = Paths.get(new URI("http://www.example.com/foo/bar.html"));
Path local = Paths.get(new URI("/bar.html"));
Files.copy(remote, local);

Currently, this throws java.nio.file.FileSystemNotFoundException: Provider "http" not installed. I could probably implement this myself but I'd rather not reinvent the wheel.

5
  • What's against Files.copy(InputStream, Path)? Do URL's constitute a path into the world that is the web? Or are they more like pointer? What are you likely to gain? Commented Jan 9, 2012 at 3:27
  • @owlstead, My library needs to return opaque Paths to users. They can copy these (read-only) Paths to the local filesystem without needing to know or care whether the file resides locally (i.e. in a database) or remotely (web server). InputStreams are missing attributes I'd like to provide my users, such as the filename or the lastModified timestamp. Commented Jan 9, 2012 at 4:06
  • Understood, but what the users see dont necessarily have to be reflected by the underlying implementation. Commented Jan 9, 2012 at 4:09
  • @owlstead, I don't understand. What do you mean? Commented Jan 9, 2012 at 4:16
  • Although the users may see it as a path, you don't necessarily have to use the new FileSystem architecture to implement it. Things like directory listings, are probably not enabled anyway. That doesn't say you cannot, but implementing it may not be worth it. Commented Jan 9, 2012 at 8:49

3 Answers 3

2

It seems like what you're really trying to do is accomplish what FTP does - copy files from one place to another. I would suggest you find better ways to do this with existing FTP code libraries.

URIs are not file system paths, so you can't treat them as such. They are addresses/resource locators that, when you go there with your browser (or another client that handles them), they trigger some action as defined by the server that's behind them. There's no standard for what that server does, hence the flexibility of web services. Therefore, if your server is doing to accept HTTP requests in this manner to facilitate file copies, you're going to have to roll your own, and pass the file data into a POST request.

To say it another way, (1) don't treat URIs like they are file system paths - they aren't, (2) find an FTP library to copy files, and/or (3) if you really want to build a web service that does this, abstract the details of the file copying via a POST request. If you do #3 understand that what your building is pretty close to custom, and that it will probably only work on a subset of sites that follow your particular design (i.e. the ones you build yourself). There's no standard set of parameters or "file copying" via POST command that I'm aware of that you can leverage to make this "just work" - you're going to have to match up your HTTP request with the web service on the server side.

Sign up to request clarification or add additional context in comments.

5 Comments

For what it's worth, someone has rolled a generic HTTP directory browser at issues.apache.org/jira/browse/VFS-199. In my case, the web server is required to follow a directory structure I specify so I'm going to need to roll a corresponding Path implementation. Thanks for helping me understand why a custom implementation is needed.
Coolio - glad I could help, and glad you found that project.
@normalocity It's almost unrelated and I'm just shooting this off of the top of my brain, but I think there isn't a method in Java 7 currently that would return a Path for a classpath resource, which would be very nice. What do you think about that? I think it would be nice, because a Path is much nicer than a URL.
@KohányiRóbert, that's actually an excellent idea! I encourage you to build it and send us the link. Seriously.
Hm, I suppose so. I generally write apps with all my resources under the path of the app, so I can consistently rely upon relative paths. However, I know plenty of people write apps that purposely go beyond their own local directory, it would probably be useful for them.
2

You can do:

URI uri = new URI("http://www.example.com/foo/bar.html");
try (InputStream is = uri.toURL().openStream()) {
    // ...
}

It will work for http, https and file out of the box, probably for few more.

For relative URIs, you have to resolve them first:

URI relative = new URI("bar.html");
URI base = new URI("http://www.example.com/foo/");
URI absolute = base.resolve(relative);
System.out.println(absolute); // prints "http://www.example.com/foo/bar.html"

Now you can call toURL().openStream() on the absolute URI.

Comments

0

I had to deal with a similar problem and wrote a little method to solve this, you can find below.

It works fine for concatenation of URL and relative suffixes. Be careful not to give suffix absolute because of the behaviour of URI resolve function.

private URI resolveURI(String root, String suffix) {
    URI uri;
    try {
        uri = new URI(root + "/").resolve(suffix);
    } catch (URISyntaxException e) {
        //log
    }
    return uri;
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.