Salı, Haziran 16, 2009

SFTP sunucudan dosya indirme

Merhabalar,

Kullandığımız sistemlerin dış sistemlerle iletişimi elbette çok büyük önem taşıyor. Tabiki iletişim sistemler arası iletişim stored procedure'lardan web servislere farklı teknolojileri kapsıyor. Ben bugün farklı bir sistemden SFTP protokolünü kullanarak dosya indirme işlemini nasıl gerçekleştireceğimiz konusunda bir örnek vermek istiyorum.

Örneğimizde kullanacağımız kütüphane commons-vfs-1.0. Commons VFS (Virtual File System), adında anlaşılacağı gibi bir dosya sistemi yöneticisi FTP,SFTP, HTTP,HTTPS, RAM, MIME gibi çok farklı dosya sistemlerini desteklemekte. Fakat birazdan örneklendireceğimiz SFTP protokolü için jsch-0.1.41 kütüphanesine ihtiyaç duyuyor.
Ayrıca aşağıdaki örnekte bağlantı cümlesindeki SFTP kelimesini FTP ile değiştirmeniz FTP sunucudan dosya almanız için yeterli.

Commons VFS kütüphanesi kullanırken dikkat edilmesi gereken en kritik nokta DefaultFileSystemManager'ın tekrar kullanılmayacağından emin olunmadığı sürece kapatılmaması. Çünkü DefaultFileSystemManager'ın kapatılması durumunda JVM yada uygulama sunucu tekrar başlatılana kadar kullanılamaz hale geliyor. Ayrıca bir JVM sadece bir DefaultFileSystemManager içerebileceğinden static olarak kullanmakta fayda var.





import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileOutputStream;

import org.apache.commons.io.FileUtils; //from commons-io
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.vfs.CacheStrategy;
import org.apache.commons.vfs.FileObject;
import org.apache.commons.vfs.FileSystemOptions;
import org.apache.commons.vfs.Selectors;
import org.apache.commons.vfs.VFS;
import org.apache.commons.vfs.impl.DefaultFileSystemManager;
import org.apache.commons.vfs.provider.sftp.SftpFileSystemConfigBuilder;


public class FileDownloader {

//Should be static and should not be forced to close.
public static DefaultFileSystemManager fsManager = null;

static {
try {

fsManager = (DefaultFileSystemManager) VFS.getManager();
//Refer to API for further info
fsManager.setCacheStrategy(CacheStrategy.ON_RESOLVE);
} catch(Exception ex) {
System.out.println(ex.getMessage());
}
}

public static void downloadUsingSFTP() throws Exception {

String destinationFolder = "YOUR_DESTINATION_FOLDER";
String userName = "USER_NAME";
String pass = "PASSWORD";
String serverIP = "SERVER_IP";
String serverPath = "DEST_FOLDER"; //Relative to user root directory
try {

FileSystemOptions fsOptions = new FileSystemOptions();
//we wont check any keys SftpFileSystemConfigBuilder.getInstance().setStrictHostKeyChecking(fsOptions, "no");

//Set user dir as root SftpFileSystemConfigBuilder.getInstance().setUserDirIsRoot(fsOptions, true);
StringBuffer uri = new StringBuffer();
uri.append("sftp://" + userName + ":" + pass + "@" + serverIP + "/" + serverPath);

System.out.println("Connection string : " + uri.toString());
FileObject fo = fsManager.resolveFile(uri.toString(), fsOptions);
FileObject[] foArray = fo.findFiles(Selectors.SELECT_FILES); //Just list files under destFolder. check api for other options

if(foArray == null || foArray.length == 0) {
throw new Exception("No files to download.");
}

logger.info("Number of files listed : " + foArray.length);
String[] files = new String[foArray.length];

for( int i = 0; i < foArray.length; i++ ) {
files[i] = FilenameUtils.getName(foArray[i].getName().getPath());
}

File folder = new File(destinationFolder);
logger.info("Create directory... - > " + destinationFolder);
FileUtils.forceMkdir(folder);
for( int i=0; i {
try {
String dataFileName = destinationFolder + "/" + files[i];
File file = new File(dataFileName);
file.createNewFile();
logger.info("Retrieving file -> " + files[i]);
FileOutputStream fos = new FileOutputStream( file );
BufferedInputStream is = new BufferedInputStream(foArray[i].getContent().getInputStream());
int content;
// do copying
while ((content = is.read()) != -1) {
fos.write(content);
}

is.close();
fos.close();
}
}catch (Exception ex) {
throw new Exception(ex.getMessage());
}


}
try {
fsManager.freeUnusedResources();
} catch (Exception ex) {
//Your logic goes here
}
}catch( Throwable e ) {
e.printStackTrace();
throw new Exception(e.getMessage());
}
}

public static void main(String args[]) {
downloadUsingSFTP();
}

}