5

I'm trying to use the org.apache.commons.vfs2 to download a file via SFTP. The problem is, the password contains the '@' char, so this causes the URI to be parsed incorrectly:

org.apache.commons.vfs2.FileSystemException: Expecting / to follow the hostname in URI

Does anyone has an idea how to get around this issue? (I can't change the password, obviously). This is the code I'm using:

String sftpUri = "sftp://" + userName + ":" + password + "@"
        + remoteServerAddress + "/" + remoteDirectory + fileName;

String filepath = localDirectory + fileName;
File file = new File(filepath);
FileObject localFile = manager.resolveFile(file.getAbsolutePath());

FileObject remoteFile = manager.resolveFile(sftpUri, opts);
localFile.copyFrom(remoteFile, Selectors.SELECT_SELF);
Ayelet
  • 1,713
  • 9
  • 29
  • 43
  • Have another look at your `sftpUri`. What happens to the `remoteServerAddress` parameter if you password contains an @? – Hannes Oct 19 '14 at 13:37
  • As I said, I know what the problem is (the URI is parsed incorectly because of the @ in the password). My question was how to solve it. – Ayelet Oct 19 '14 at 13:39
  • 1
    Sry. I didn't see. Have a look at http://stackoverflow.com/questions/6718471/escaping-username-characters-in-basic-auth-urls – Hannes Oct 19 '14 at 13:42
  • This might be a silly question, but how do encode the password? – Ayelet Oct 19 '14 at 14:06
  • You can use `URLEncoder.encode(...)` from `java.net`. Do only encode username and password. – Hannes Oct 19 '14 at 15:03

2 Answers2

6

Use an actual URI constructor instead of hand-rolling your own:

String userInfo = userName + ":" + password;
String path = remoteDirectory + filename;  // Need a '/' between them?
URI sftpUri = new URI("sftp", userInfo, remoteServerAddress, -1, path, null, null);
...
FileObject remoteFile = manager.resolveFile(sftpUri.toString(), opts);
Kenster
  • 23,465
  • 21
  • 80
  • 106
  • and make sure path starts with a / and does not use windows \ characters. Or you convert it from a file like this: `new File("c:\\temp").toURI().getPath()` – eckes Jan 05 '15 at 17:33
0

You need to encode the your password by UriParser.encode(), you can change your code like below:

you code:

String sftpUri = "sftp://" + userName + ":" + password + "@"
        + remoteServerAddress + "/" + remoteDirectory + fileName;

change to:

String sftpUri = "sftp://" + userName + ":" + **UriParser.encode(password, "@".toCharArray())**+ "@"
        + remoteServerAddress + "/" + remoteDirectory + fileName;

Hope it help, thank you.

Procrastinator
  • 2,526
  • 30
  • 27
  • 36
Ryan
  • 1
  • 1