java Mina sftp,如何使用Java中的Apache Mina SSHD SFTP服务器处理传入文件

Currently i am working on a SFTP protocol.I have created SFTP client Using Jsch Library and SFTP Server using Apache Mina Sshd library.I have made connection between them and can successfully send files to SFTP server.Now i am working on creating a SFTP server side file handler that handles the incoming files.As a example let say SFTP server can receive files from SFTP client but currently in my implementation there is no way to notify when file is arrived into server.I just go server root folder and see if there is a files available.That is how i know if files are arrived.

I would like to implement that when files arrive into server it will notify user to files are arrived and files content.(file Name and other details).But the problem is that i am new to Apache Mina sshd API.i have gone through documentation but i couldn't figured it out.

Please I would like know that if there are any already implemented listeners for handle incoming files in Apache Mina Sshd server or if not how can i implement my own listener for incoming files.

SFTP Server Code

public class SftpServerStarter {

private SshServer sshd;

private final static Logger logger = LoggerFactory.getLogger(SftpServerStarter.class);

public void start(){

sshd = SshServer.setUpDefaultServer();

sshd.setPort(22);

sshd.setHost("localhost");

sshd.setPasswordAuthenticator(new MyPasswordAuthenticator());

sshd.setPublickeyAuthenticator(new MyPublickeyAuthenticator());

sshd.setKeyPairProvider(new SimpleGeneratorHostKeyProvider());

sshd.setSubsystemFactories(Arrays.>asList(new SftpSubsystem.Factory()));

sshd.setCommandFactory(new ScpCommandFactory());

sshd.setFileSystemFactory(new VirtualFileSystemFactory("C:/root"));

try {

logger.info("Starting ...");

sshd.start();

logger.info("Started");

} catch (IOException e) {

// TODO Auto-generated catch block

e.printStackTrace();

logger.info("Can not Start Server");

}

}

}

解决方案

I started out using @gihan's suggestion, but I ran into some problems with the File Monitors processing the file before the user was finished uploading it on some clients.

Here is the solution I found from poking around in Mina's source code. In spite of the sparse, useless documentation on Apache Mina's site, I think this is the way they intended for developers to use their library.

NOTE: Since your needs are probably different than mine, keep in mind that this may not be a copy-and-paste solution. You will probably need to adapt this code to suit your needs, but I'm fairly confident that this code does provide the key to the solution you're looking for.

Step 1: Implement SftpEventListener

Create your own class that implements org.apache.sshd.server.subsystem.sftp.SftpEventListener. Here's mine as an example. My implementation is set up to run a series of registered FileUploadCompleteListener methods whenever a file is newly uploaded or overwritten, and block user attempts to navigate or create directories.

public class SFTPServiceSFTPEventListener implements SftpEventListener {

Logger logger = Logger.getLogger(SFTPServiceSFTPEventListener.class);

SFTPService service;

public SFTPServiceSFTPEventListener(SFTPService service) {

this.service = service;

}

public interface FileUploadCompleteListener {

void onFileReady(File file);

}

private List fileReadyListeners = new ArrayList();

public void addFileUploadCompleteListener(FileUploadCompleteListener listener) {

fileReadyListeners.add(listener);

}

public void removeFileUploadCompleteListener(FileUploadCompleteListener listener) {

fileReadyListeners.remove(listener);

}

@Override

public void initialized(ServerSession serverSession, int version) {

}

@Override

public void destroying(ServerSession serverSession) {

}

@Override

public void open(ServerSession serverSession, String remoteHandle, Handle localHandle) {

File openedFile = localHandle.getFile().toFile();

if (openedFile.exists() && openedFile.isFile()) {

}

}

@Override

public void read(ServerSession serverSession, String remoteHandle, DirectoryHandle localHandle, Map entries) {

}

@Override

public void read(ServerSession serverSession, String remoteHandle, FileHandle localHandle, long offset, byte[] data, int dataOffset, int dataLen, int readLen) {

}

@Override

public void write(ServerSession serverSession, String remoteHandle, FileHandle localHandle, long offset, byte[] data, int dataOffset, int dataLen) {

}

@Override

public void blocking(ServerSession serverSession, String remoteHandle, FileHandle localHandle, long offset, long length, int mask) {

}

@Override

public void blocked(ServerSession serverSession, String remoteHandle, FileHandle localHandle, long offset, long length, int mask, Throwable thrown) {

}

@Override

public void unblocking(ServerSession serverSession, String remoteHandle, FileHandle localHandle, long offset, long length) {

}

@Override

public void unblocked(ServerSession serverSession, String remoteHandle, FileHandle localHandle, long offset, long length, Boolean result, Throwable thrown) {

}

@Override

public void close(ServerSession serverSession, String remoteHandle, Handle localHandle) {

File closedFile = localHandle.getFile().toFile();

if (closedFile.exists() && closedFile.isFile()) {

logger.info(String.format("User %s closed file: \"%s\"", serverSession.getUsername(), localHandle.getFile().toAbsolutePath()));

this.service.UserWroteFile(serverSession.getUsername(), localHandle.getFile());

for (FileUploadCompleteListener fileReadyListener : fileReadyListeners) {

fileReadyListener.onFileReady(closedFile);

}

}

}

@Override

public void creating(ServerSession serverSession, Path path, Map attrs) throws UnsupportedOperationException {

logger.warn(String.format("Blocked user %s attempt to create a directory \"%s\"", serverSession.getUsername(), path.toString()));

throw new UnsupportedOperationException("Creating sub-directories is not permitted.");

}

@Override

public void created(ServerSession serverSession, Path path, Map attrs, Throwable thrown) {

String username = serverSession.getUsername();

logger.info(String.format("User %s created: \"%s\"", username, path.toString()));

service.UserWroteFile(username, path);

}

@Override

public void moving(ServerSession serverSession, Path path, Path path1, Collection collection) {

}

@Override

public void moved(ServerSession serverSession, Path source, Path destination, Collection collection, Throwable throwable) {

String username = serverSession.getUsername();

logger.info(String.format("User %s moved: \"%s\" to \"%s\"", username, source.toString(), destination.toString()));

service.UserWroteFile(username, destination);

}

@Override

public void removing(ServerSession serverSession, Path path) {

}

@Override

public void removed(ServerSession serverSession, Path path, Throwable thrown) {

}

@Override

public void linking(ServerSession serverSession, Path source, Path target, boolean symLink) throws UnsupportedOperationException {

logger.warn(String.format("Blocked user %s attempt to create a link to \"%s\" at \"%s\"", serverSession.getUsername(), target.toString(), source.toString()));

throw new UnsupportedOperationException("Creating links is not permitted");

}

@Override

public void linked(ServerSession serverSession, Path source, Path target, boolean symLink, Throwable thrown) {

}

@Override

public void modifyingAttributes(ServerSession serverSession, Path path, Map attrs) {

}

@Override

public void modifiedAttributes(ServerSession serverSession, Path path, Map attrs, Throwable thrown) {

String username = serverSession.getUsername();

service.UserWroteFile(username, path);

}

}

Step 2: Add an instance of your listener to your server

Once you've implemented your class, all you need to do is instantiate it and add it to your server using an SftpSubsystemFactory before calling start() on your server:

// Your SSHD Server

SshServer sshd = SshServer.setUpDefaultServer();

SftpSubsystemFactory sftpSubsystemFactory= new SftpSubsystemFactory();

// This is where to put your implementation of SftpEventListener

SFTPServiceSFTPEventListener sftpEventListener = new SFTPServiceSFTPEventListener(this);

sftpEventListener.addFileUploadCompleteListener(new SFTPServiceSFTPEventListener.FileUploadCompleteListener() {

@Override

public void onFileReady(File file) {

try {

doThingsWithFile(file);

} catch (Exception e) {

logger.warn(String.format("An error occurred while attempting to do things with the file: \"%s\"", file.getName()), e);

}

}

});

sftpSubsystemFactory.addSftpEventListener(sftpEventListener);

List> namedFactoryList = new ArrayList>();

namedFactoryList.add(sftpSubsystemFactory);

sshd.setSubsystemFactories(namedFactoryList);

// Do your other init stuff...

sshd.start();

Once you've done that, your implementation of SftpEventListener will start automatically responding to the events you've implemented. Mine basically just responds to when the user closes the file (which occurs when the file upload is complete), but as I said, you can feel free to implement the other methods to respond to other events.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值