I am trying to copy local system file to server
package classes;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.Properties;
import org.apache.commons.vfs.FileObject;
import org.apache.commons.vfs.FileSystemOptions;
import org.apache.commons.vfs.Selectors;
import org.apache.commons.vfs.impl.StandardFileSystemManager;
import org.apache.commons.vfs.provider.sftp.SftpFileSystemConfigBuilder;
public class SendMyFiles {
public static void main(String[] args) {
SendMyFiles sendMyFiles = new SendMyFiles();
String fileToFTP = "zcol_30092013.xls";
sendMyFiles.startFTP(fileToFTP);
}
public boolean startFTP(String fileToFTP){
Properties prop = new Properties();
InputStream in = getClass().getResourceAsStream("/config.properties");
StandardFileSystemManager manager = new StandardFileSystemManager();
try {
prop.load(in);
String serverAddress = prop.getProperty("serverAddress").trim();
String userId = prop.getProperty("userId").trim();
String password = prop.getProperty("password").trim();
String remoteDirectory = prop.getProperty("remoteDirectory").trim();
String localDirectory = prop.getProperty("localDirectory").trim();
System.out.println("Cheking values "+serverAddress+" "+userId+" "+password+" "+remoteDirectory+" "+localDirectory);
//check if the file exists
String filepath = localDirectory;
System.out.println("filepath "+filepath);
File file = new File(filepath);
System.out.println(file+" "+file.exists());
if (!file.exists())
throw new RuntimeException("Error. Local file not found");
//Initializes the file manager
manager.init();
//Setup our SFTP configuration
FileSystemOptions opts = new FileSystemOptions();
SftpFileSystemConfigBuilder.getInstance().setStrictHostKeyChecking(
opts, "no");
SftpFileSystemConfigBuilder.getInstance().setUserDirIsRoot(opts, true);
SftpFileSystemConfigBuilder.getInstance().setTimeout(opts, 10000);
//Create the SFTP URI using the host name, userid, password, remote path and file name
String sftpUri= "sftp://" + userId + ":" + password + "@" + serverAddress + "/"
+ remoteDirectory+ fileToFTP;
// Create local file object
System.out.println("sftp uri "+sftpUri);
System.out.println(file.getAbsolutePath());
FileObject localFile = manager.resolveFile(file.getAbsolutePath());
// Create remote file object
FileObject remoteFile = manager.resolveFile(sftpUri, opts);
// Copy local file to sftp server
remoteFile.copyFrom(localFile, Selectors.SELECT_SELF);
System.out.println("File upload successful");
}
catch (Exception ex) {
ex.printStackTrace();
return false;
}
finally {
manager.close();
}
return true;
}
}
While executing the code getting below exception:
org.apache.commons.vfs.FileSystemException: Invalid absolute URI "sftp://vmsorbit:***@172.16.16.148/universe/files/zcol_30092013.xls".
at org.apache.commons.vfs.provider.AbstractOriginatingFileProvider.findFile(AbstractOriginatingFileProvider.java:62)
at org.apache.commons.vfs.impl.DefaultFileSystemManager.resolveFile(DefaultFileSystemManager.java:692)
at org.apache.commons.vfs.impl.DefaultFileSystemManager.resolveFile(DefaultFileSystemManager.java:620)
at classes.SendMyFiles.startFTP(SendMyFiles.java:67)
at classes.SendMyFiles.main(SendMyFiles.java:23)
Caused by: org.apache.commons.vfs.FileSystemException: Expecting / to follow the hostname in URI "sftp://vmsorbit:***@172.16.16.148/universe/files/zcol_30092013.xls".
at org.apache.commons.vfs.provider.HostFileNameParser.extractToPath(HostFileNameParser.java:155)
at org.apache.commons.vfs.provider.URLFileNameParser.parseUri(URLFileNameParser.java:49)
at org.apache.commons.vfs.provider.AbstractFileProvider.parseUri(AbstractFileProvider.java:188)
at org.apache.commons.vfs.provider.AbstractOriginatingFileProvider.findFile(AbstractOriginatingFileProvider.java:58)
... 4 more
getting error at line
FileObject localFile = manager.resolveFile(file.getAbsolutePath());
The password contains special character @
.
As @martin-prikryl's answer states, certain characters can't appear in their raw form in the username and password fields, or else they will make the URI invalid.
The root cause here is that you're using simple string concatenation to construct the URI:
String sftpUri= "sftp://" + userId + ":" + password + "@" + serverAddress + "/"
+ remoteDirectory+ fileToFTP;
Java has URI and URL classes which can be used to construct URIs and URLs from individual fields. They will handle encoding each field properly. You should use one of them instead of rolling your own logic:
import java.net.URI;
import java.net.URISyntaxException;
public class URITest {
public static void main(String[] args) throws URISyntaxException {
String user = "user";
String passwd = "p@ss/ord";
String host = "example.com";
String path = "/some/path";
String userInfo = user + ":" + passwd;
URI uri = new URI("sftp", userInfo, host, -1,
path, null, null);
System.out.println(uri.toString());
}
}
This prints:
sftp://user:p%40ss%[email protected]/some/path
If your password contains @
, the URL parser considers it a userinfo/hostname separator. It then scans for a hostname, stopping on the next @
, which separates the actual hostname. Next it checks that the first character after the hostname is /
, what it is not, as it is @
. The logic does not make much sense to me, but explains the confusing error message
Expecting / to follow the hostname in URI
But in any case, even if the logic was better, you cannot have a literal @
in your password or username. You have to URL-encode it to %40
.
If your username/password is variable, you should better encode it generically using the UriParser.encode
:
public static String encode(String decodedStr)
Note that the comment in the documentation is wrong. It says the method "Removes %nn encodings from a string.", while it actually adds them.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With