Fileupload application not working as jar - java

Spring boot application. User selects server of their choice and a file on their local system and the file gets SFTP to that server.
This works by: input stream reading the file into a folder within the root project. The sftp method needs the file path to work. Since I'm unable to get the file path of the file on the users system and just get the file, I bring it locally and then supply the path from there.
This work perfectly when running my project from intellij and NOT so perfectly when packaged as a jar.
After some reading, it looks like it's not great to bring in a file into a jar. Any ideas on a route to take now? Thanks
public void SFTP(MultipartFile file, String friendlyName, String filePath) throws Exception {
String host = "10.3.152.245"; //host:IP
String user = "cloud";
String password = "Password1";
System.out.println("File path: " + filePath);
try {
String fileName = renameLocal(file);
java.util.Properties config = new java.util.Properties();
JSch jsch = new JSch();
Session session = jsch.getSession(user, host, 22);
session.setPassword(password);
config.put("StrictHostKeyChecking", "no");
session.setConfig(config);
session.connect();
ChannelSftp sftpChannel = (ChannelSftp) session.openChannel("sftp");
sftpChannel.connect();
sftpChannel.cd("/");
sftpChannel.cd(filePath);
sftpChannel.put("\\upload-dir\\" + fileName, ".");
sftpChannel.rename(filePath + "/" + fileName, filePath + "/" + file.getOriginalFilename());
session.disconnect();
sftpChannel.disconnect();
Path path = FileSystems.getDefault().getPath(".\\upload-dir\\" + fileName);
Files.delete(path);
}catch (Exception e){
throw new Exception();
}
}
the method above is the SFTP method that's called when a user uploads a file. Static host user and pass for now. As you see, I'm putting the file locally (method not here) in the upload-dir. Then providing upload-dir\filename to the sftpChannel.put method

Related

How to get only directories and text files using SFTP channel of JSch?

Hi I am developing an application which connects to remote server and browses through different directories.
Here I want to show only directories and text files to user. Using SFTP channel in JSch, I can execute ls method. But this method can give me result for either in this format "*" or "*.txt". Using ls separately I can get directories list and text file list. Since I am using it separately I have to use 2 different ls methods like:
sftpChannel.ls("*");
sftpChannel.ls("*.txt");
1st gives me all entries from which I have to loop and filter directories. In second, I get all text files.
How can I get directories list and text file list using minimum code. I don't want to loop twice. Thanks
Use ls(""). Then loop the returned entries, and select only those you want.
I.e. those that have LsEntry.getFilename() ending with ".txt" or LsEntry.getAttrs().isDir().
We can use like this, read directories and files also.
public List<String> readRemoteDirectory(String location){
System.out.println("Reading location : "+location);
Session session = null;
Channel channel = null;
ChannelSftp channelSftp = null;
List<String> filesList = new ArrayList<String>();
String separator = getSeparator();
try{
JSch jsch = new JSch();
session = jsch.getSession(remote_server_user,remote_server_ip,22);
session.setPassword(remote_server_password);
java.util.Properties config = new java.util.Properties();
config.put("PreferredAuthentications", "publickey,keyboard-interactive,password");
session.setConfig(config);
session.connect();
channel = session.openChannel("sftp");
channel.connect();
channelSftp = (ChannelSftp)channel;
channelSftp.cd(location);
Vector filelist = channelSftp.ls("*");
for(int i=0; i<filelist.size();i++){
LsEntry entry = (LsEntry) filelist.get(i);
if (".".equals(entry.getFilename()) || "..".equals(entry.getFilename())) {
continue;
}
if(entry.getAttrs().isDir()){
System.out.println(entry.getFilename());
//System.out.println("Entry"+location+separator+entry.getAttrs());
filesList.add(entry.getFilename());
}
}
}catch(Exception ex){
ex.printStackTrace();
logger.debug(ex.getMessage());
if(ex.getMessage().equals("No such file")){
logger.debug("No Such File IF");
}
}finally{
channel.disconnect();
session.disconnect();
}
return filesList;
}

Check if file exists using Apache Commons VFS2

I would like to ask if there is a way how to check if file already exists in the folder using only Apache Commons.
I have method which uploads into the SFTP folder but it overwrites current files anytime the method is running. The method is set to run every 5 minutes. I need a code which will create and if statement which checks if the file is not at the SFTP location already and then, if not executes my copy method, if there is a file, then skips it.
My copy method looks like this
private void copyFileSFTP(File model, String hour) throws IOException {
StandardFileSystemManager manager = new StandardFileSystemManager();
String dest = String.format("%s/%s/model/%s", destinationPath, hour,
model.getName());
remoteDirectory = String.format("%s/%s/model/", destinationPath, hour);
try {
if (!model.exists())
LOG.error("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,
false);
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 + model.getName();
**HERE I NEED THE CHECK IF THE MODEL EXISTS ALREADY ON SFTP**
// Create local file object
FileObject localFile = manager.resolveFile(model.getAbsolutePath());
// Create remote file object
FileObject remoteFile = manager.resolveFile(sftpUri, opts);
// Copy local file to sftp server
remoteFile.copyFrom(localFile, Selectors.SELECT_SELF);
LOG.info("File upload successful");
LOG.info("New file has been created.");
LOG.info(dest);
} catch (Exception ex) {
LOG.error(ex);
handleBadPath(model, hour);
} finally {
manager.close();
}
}
Thank you for help.
Use FileObject.exists() method.
See https://commons.apache.org/proper/commons-vfs/commons-vfs2/apidocs/org/apache/commons/vfs2/FileObject.html#exists--

Using Apache Commons VFS- SFTP, uploading to a server

I'm attempting to use Apache Commons VFS to SFTP a file onto a server, but I keep getting the following error:
java.lang.RuntimeException: org.apache.commons.vfs2.FileSystemException: Could not connect to SFTP server at "sftp://user:***#xxx.x.xxx.xxx/".
Is it normal for it to not include the remote file path (remoteFilePath) here? It's in my code to include it in the connection string (see below)
I have the following jars included in my pom:
commons-logging-1.1.3.jar
commons-vfs2-2.0.jar
hamcrest-core-1.3.jar
jsch-0.1.50.jar
Code:
public void SftpMethod(String strMsg, String tableName){
String host = "xxx.x.xxx.xxx";
String user = "user";
String pass = "password!";
String localFilePath = "C:\\Users\\exampleDir\\Desktop\\loc.dat";
String remoteFilePath = "/dir/home/user/export/loc.dat";
StandardFileSystemManager manager = new StandardFileSystemManager();
File file = new File(localFilePath);
if (!file.exists())
throw new RuntimeException("Error. Local file not found");
try{
manager.init();
// Create local file object
FileObject localFile = manager.resolveFile(file.getAbsolutePath());
// Create remote file object
FileObject remoteFile = manager.resolveFile(
createConnectionString(host, user, pass, remoteFilePath),
createDefaultOptions());
// Copy local file to SFTP server
remoteFile.copyFrom(localFile, Selectors.SELECT_SELF);
System.out.println("File upload success");
}catch(IOException e){
throw new RuntimeException(e);
}finally{
manager.close();
}
}
public static String createConnectionString(String hostName, String username, String password, String remoteFilePath) {
return "sftp://" + username + ":" + password + "#" + hostName + "/" + remoteFilePath;
}
public static FileSystemOptions createDefaultOptions() throws FileSystemException {
// Create SFTP options
FileSystemOptions opts = new FileSystemOptions();
// SSH Key checking
SftpFileSystemConfigBuilder.getInstance().setStrictHostKeyChecking(opts, "no");
/*
* Using the following line will cause VFS to choose File System's Root
* as VFS's root. If I wanted to use User's home as VFS's root then set
* 2nd method parameter to "true"
*/
// Root directory set to user home
SftpFileSystemConfigBuilder.getInstance().setUserDirIsRoot(opts, true);
// Timeout is count by Milliseconds
SftpFileSystemConfigBuilder.getInstance().setTimeout(opts, 10000);
return opts;
}
Without the full stack trace its hard to give a conclusive answer, but this is what I saw recently:
Caused by: org.apache.commons.vfs2.FileSystemException: Could not load private key from "/Users/<user>/.ssh/id_rsa".
at org.apache.commons.vfs2.provider.sftp.SftpClientFactory.createConnection(SftpClientFactory.java:131)
Unfortunately, I wasn't trying to use a public/private key. I was only intending to log in with a username/password. I needed a way for it to stop trying to read my private key.
The root cause was that the code was using a default location for my key, and attempting to read it (even though thats not what I wanted).
So the workaround was to override the default location by setting the following property:
System.setProperty("vfs.sftp.sshdir", "/");
This bypassed the attempt to read the ssh key altogether, and successfully connected.

From where two extra files named ( '.' and '..' ) came by getting file names from Vector in jSch SFTP

I made a simple program using jSch to print the name of total files in a remote directory.
In the directory, there are only 7 files but, on my console, I am getting two extra files with name . and ...
From where these files came, or its a garbage???
My Java code:
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.Session;
import java.util.Vector;
public class DownloadFileSFTP {
public static void main(String[] s){
String user = "user";
String password = "1234";
String host = "remoteIP";
int port = 22;
String sourcePath = "/home/remoteSFTP_Files/";
String destinationPath = "/home/user/SFTP_files/";
Session session = null;
ChannelSftp sftp = null;
try {
JSch jsch = new JSch();
session = jsch.getSession(user, host, port);
session.setPassword(password);
session.setConfig("StrictHostKeyChecking", "no");
session.connect();
System.out.println("Session created");
sftp = (ChannelSftp) session.openChannel("sftp");
sftp.connect();
System.out.println("SFTP Channel connected");
Vector totalFiles = sftp.ls(sourcePath);
for(int i = 0; i < totalFiles.size(); i++){
ChannelSftp.LsEntry ls = (ChannelSftp.LsEntry) totalFiles.get(i);
System.out.println("File Name: " + ls.getFilename());
}
} catch (Exception e){
e.printStackTrace();
} finally {
sftp.exit();
sftp.disconnect();
session.disconnect();
}
}
}
O/P in my console:
Session created
SFTP Channel connected
File Name: campMonitorHome.jsp
File Name: asm-3.1.jar
File Name: didLatest_dump.sql
File Name: PieChartJson.java
File Name: demoFile.txt
File Name: .
File Name: jquery.jqplot.min.css
File Name: showgraphicalMonitor.jsp
File Name: ..
It's simply showing the "." current directory and ".." parent directory.
I guess people who haven't used terminals never come accross them :)
In your execution folder, along with all your files there are two entities called "." and ".." which represent the present folder and the parent folder respectively. Those are not real files, but keywords reserved by a Unix system to have a relative reference to call them.
This way you can make scripts to relate to those folders without writing a whole address.
You can simply ignore these keywords by using a remove method from totalFiles.

JSch - Server "home" path is always "/" with FreeSSHd and can't change directory

I set-up a server with FreeSSHd and am able to Putty it, including changing directories and listing files. I have some example .txt files and a folder in the home directory. I set the home directory on my server to "C:\SFTP" using FreeSSHd (as opposed to defining a HOME variable with the directory being "$HOME\").
Apparently, when using JSch,
JSch jsch = new JSch();
session = jsch.getSession(username,host,port);
jsch.addIdentity(key.getAbsolutePath());
java.util.Properties config = new java.util.Properties();
config.put("StrictHostKeyChecking", "no");
session.setConfig(config);
session.setUserInfo(new MyUserInfo());
session.connect();
channel = session.openChannel("sftp");
channel.connect();
channelSftp = (ChannelSftp)channel;
System.out.println("Home: "+channelSftp.getHome());
the last line prints just "Home: /". Any attempts (made immediately after above code) to use
channelSftp.cd(WORKINGDIR);
results in
2: No such file
at com.jcraft.jsch.ChannelSftp.throwStatusError(ChannelSftp.java:2833)
at com.jcraft.jsch.ChannelSftp._stat(ChannelSftp.java:2185)
at com.jcraft.jsch.ChannelSftp.get(ChannelSftp.java:1295)
at com.jcraft.jsch.ChannelSftp.get(ChannelSftp.java:1267)
at test.SFTPTest.main(SFTPTest.java:71)
I think if I got to the root of why JSch does not have the correct home path (or any?) this would work. Also, strangely enough I upload and download files no problem using put() and get().
I've heard all kinds of things where people look into the source and find it does strange things in resolving paths and something with a method called "_realPath()" and superfluous leading/trailing "/" but I don't even have it telling me the home directory is correct after connecting.
Any ideas?
ThankĀ“s everybody for your comments.
OS windows XP,I installed FreeSSHd and setting the default directory, then, when I tryng connect by console ssh, the directory was "/", I writing chdir but directory was: C:\Windows\system32\ this is very confused...
My Java code:
public void recursiveFolderUpload(String sourcePath, String destinationPath) throws FileNotFoundException {
if (c == null || session == null || !session.isConnected() || !c.isConnected()) {
log.debug("Connection to server is closed. Open it first.");
}
try {
// c.put(sourceFile, destinationFile);
// log.info("Upload successfull.");
File sourceFile = new File(sourcePath);
if (sourceFile.isFile()) {
// copy if it is a file
c.cd(destinationPath);
if (!sourceFile.getName().endsWith("."))
c.put(new FileInputStream(sourceFile), sourceFile.getName(), c.OVERWRITE);
} else {
log.info("Inside else " + sourceFile.getName());
File[] files = sourceFile.listFiles();
if (files != null && !sourceFile.getName().startsWith(".")) {
log.info("Directory remote server: " + c.pwd());
c.cd(destinationPath);
SftpATTRS attrs = null;
// check if the directory is already existing
try {
attrs = c.stat(destinationPath + sourceFile.getName());
} catch (Exception e) {
log.warn(destinationPath + sourceFile.getName() + " not found");
//e.printStackTrace();
}
// else create a directory
if (attrs != null) {
log.info("Directory exists IsDir : " + attrs.isDir());
} else {
log.info("Creating dir /" + sourceFile.getName());
c.mkdir(sourceFile.getName());
}
for (File f : files) {
if(!f.getName().contains(".dtd")){
log.info("Uploading file: " + f.getAbsoluteFile());
recursiveFolderUpload(f.getAbsolutePath(), destinationPath + sourceFile.getName() + "/");
}
}
}
}
} catch (SftpException e) {
e.printStackTrace();
}
}
My solution was only put the "/" en the input parameter destinationPath of method called recursiveFolderUpload
In other words, my properties file than so:
properties.host = IP
properties.user = user
properties.pass = pass
properties.port = port
properties.dir = / ---> This points to the directory configured by default in opensshd within windows
Thank so much everthing again.
SFTP directory should be the directory of the current user is not necessarily SFTP services with the directory, I also encountered the same problem, because I am with the directory and the user's default directory settings.

Categories

Resources