All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.alogic.vfs.sftp.SFtp Maven / Gradle / Ivy

package com.alogic.vfs.sftp;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import com.alogic.terminal.sshj.Authenticator;
import com.alogic.vfs.core.VirtualFileSystem;
import com.anysoft.util.IOTools;
import com.anysoft.util.Properties;
import com.anysoft.util.PropertiesConstants;
import net.schmizz.sshj.SSHClient;
import net.schmizz.sshj.sftp.*;
import net.schmizz.sshj.transport.verification.PromiscuousVerifier;
import net.schmizz.sshj.xfer.FilePermission;

/**
 * 基于sftp的vfs
 * 
 * @author weibj
 * @version 1.6.7.9 [20170201 duanyy] 
* - 采用SLF4j日志框架输出日志
* * @version 1.6.7.11 [20170203 duanyy]
* - 增加toString实现
* * @version 1.6.7.13 [20170206 duanyy]
* - 写文件接口增加permissions参数,以便在创建文件时指定文件的权限
* * @version 1.6.7.18 [20170227 duanyy]
* - 修正SFtp的java.lang.NegativeArraySizeException异常
* * @version 1.6.9.3 [20170615 duanyy]
* - 增加move的方法
* * @version 1.6.9.4 [20170615 duanyy]
* - 统一各实现的文件名匹配规则为正则表达式匹配
* * @version 1.6.12.44 [20191023 duanyy]
* - 增加支持证书登录
*/ public class SFtp extends VirtualFileSystem.Abstract { protected SSHClient sshClient = null; protected SFTPClient sftpClient = null; /* * sftp的主机 */ protected String host; /* * sftp的端口号 */ protected int port = 22; /* * 创建目录的权限值 */ protected int permissions = 0777; private static int ONCE_MAX_BYTES = 32768; protected Authenticator authenticator = null; public SFtp() { } @Override public String toString(){ return String.format("%s[sftp://%s:%d%s]",id,host,port,root); } @Override public void configure(Properties p) { host = PropertiesConstants.getString(p, "host", host); port = PropertiesConstants.getInt(p, "port", port); id = PropertiesConstants.getString(p, "id", "default", true); dftPattern = PropertiesConstants.getString(p, "dftPattern", "[.]*[^.]+.*"); root = PropertiesConstants.getString(p, "root", root); permissions = PropertiesConstants.getInt(p, "permissions", permissions); Authenticator.TheFactory factory = new Authenticator.TheFactory(); try{ authenticator = factory.newInstance(PropertiesConstants.getString(p, "auth", "WithPassword"),p); }catch (Exception ex){ LOG.error("Can not create authenticator."); } } protected SFTPClient getClient() { if (sftpClient == null) { synchronized (this) { if (sftpClient == null) { try { sshClient = new SSHClient(); sshClient.addHostKeyVerifier(new PromiscuousVerifier()); sshClient.connect(this.host,this.port); if (authenticator != null){ authenticator.authenticate(sshClient); } sftpClient = sshClient.newSFTPClient(); } catch (Exception e) { LOG.error(e.getMessage()); } } } } return sftpClient; } protected void getFileInfo(FileAttributes attrs, Map json) { json.put("dir", attrs.getType() == FileMode.Type.DIRECTORY); json.put("lastModified", attrs.getMtime()); json.put("lastAccess", attrs.getAtime()); json.put("length", attrs.getSize()); json.put("symLink", attrs.getType() == FileMode.Type.SYMLINK); json.put("groupId", attrs.getGID()); json.put("permission", Integer.toOctalString(FilePermission.toMask(attrs.getPermissions()))); json.put("ownerId", attrs.getUID()); } @Override protected String getRealPath(String path) { return root + File.separatorChar + path; } @Override public List listFiles(String path, String pattern, int offset, int limit) { List result = new ArrayList(); SFTPClient client = getClient(); String realPath = getRealPath(path); try { if (isDir(path)) { List files = client.ls(realPath); if (files != null) { Pattern p = Pattern.compile(pattern); int current = 0; for (int i = 0; i < files.size(); i++) { RemoteResourceInfo entry = files.get(i); String filename = entry.getName(); Matcher matcher = p.matcher(filename); if (matcher.matches()) { if (current >= offset) { result.add(filename); } current++; if (current >= offset + limit) { break; } } } } } } catch (IOException e) { LOG.error(e.getMessage()); } return result; } @Override public void listFiles(String path, String pattern, Map json, int offset, int limit) { SFTPClient client = getClient(); String realPath = getRealPath(path); try { if (isDir(path)) { List result = new ArrayList(); List files = client.ls(realPath); if (files != null) { Pattern p = Pattern.compile(pattern); int current = 0; for (int i = 0; i < files.size(); i++) { RemoteResourceInfo file = files.get(i); String filename = file.getName(); Matcher matcher = p.matcher(filename); if (matcher.matches()) { if (current >= offset) { Map map = new HashMap(); getFileInfo(file.getAttributes(), map); map.put("name", filename); map.put("path", path + File.separator + filename); result.add(map); } current++; if (current >= offset + limit) { break; } } } json.put("file", result); json.put("offset", offset); json.put("limit", limit); json.put("total", current); json.put("path", path); } } } catch (IOException e) { LOG.error(e.getMessage()); } } @Override public boolean deleteFile(String path) { SFTPClient client = getClient(); String realPath = getRealPath(path); try { if (isDir(path)) { deleteFolder(path); client.rmdir(getRealPath(path)); } else { client.rm(realPath); } return true; } catch (IOException e) { LOG.error(e.getMessage()); return false; } } //递归删除文件夹 private Boolean deleteFolder(String folderPath) { Boolean result = true; SFTPClient client = getClient(); List fileLists = new ArrayList(); fileLists = listFiles(folderPath, dftPattern, 0, Integer.MAX_VALUE); for (String file : fileLists) { try { String path = folderPath + File.separatorChar + file; if (isDir(path)) { deleteFolder(path); client.rmdir(getRealPath(path)); } else { client.rm(getRealPath(path)); } } catch (IOException e) { LOG.error(e.getMessage()); result = false; } } return result; } @Override public boolean exist(String path) { SFTPClient client = getClient(); path = getRealPath(path); try { client.stat(path); } catch (Exception e) { return false; } return true; } @Override public boolean isDir(String path) { SFTPClient client = getClient(); path = getRealPath(path); try { FileAttributes attrs = client.stat(path); return attrs == null ? false : (attrs.getType()==FileMode.Type.DIRECTORY); } catch (IOException e) { LOG.error(e.getMessage()); return false; } } @Override public long getFileSize(String path) { SFTPClient client = getClient(); path = getRealPath(path); try { FileAttributes attrs = client.stat(path); return attrs == null ? 0 : attrs.getSize(); } catch (IOException e) { LOG.error(e.getMessage()); return 0; } } @Override public void getFileInfo(String path, Map json) { SFTPClient client = getClient(); path = getRealPath(path); try { FileAttributes attrs = client.stat(path); if (attrs != null) { getFileInfo(attrs, json); json.put("path", path); } } catch (IOException e) { LOG.error(e.getMessage()); } } @Override public boolean makeDirs(String path) { SFTPClient client = getClient(); String arrPath[] = path.split(File.separatorChar + ""); String pathtmp = ""; for (int i = 0; i < arrPath.length; i++) { pathtmp += File.separatorChar + arrPath[i]; try { if (!isDir(pathtmp)) { client.mkdir(getRealPath(pathtmp)); } } catch (IOException e) { LOG.error(e.getMessage()); return false; } } return true; } private byte[] byteMerger(byte[] byte_1, byte[] byte_2) { byte[] byte_3 = new byte[byte_1.length + byte_2.length]; System.arraycopy(byte_1, 0, byte_3, 0, byte_1.length); System.arraycopy(byte_2, 0, byte_3, byte_1.length, byte_2.length); return byte_3; } @Override public InputStream readFile(String path) { SFTPClient client = getClient(); String realPath = getRealPath(path); int startid = 0; try { if (!isDir(path)) { RemoteFile file = client.open(realPath); return file.new RemoteFileInputStream(); } return null; } catch (IOException e) { LOG.error(e.getMessage()); return null; } } @Override public void finishRead(String path, InputStream in) { IOTools.close(in); } @Override public OutputStream writeFile(String path, int permissions) { final SFTPClient client = getClient(); String realPath = getRealPath(path); try { if (!exist(path)) { RemoteFile file = client.open(realPath, EnumSet.of(OpenMode.WRITE, OpenMode.CREAT, OpenMode.TRUNC)); return file.new RemoteFileOutputStream(); } return null; } catch (IOException e) { LOG.error(e.getMessage()); return null; } } @Override public OutputStream writeFile(String path) { return writeFile(path,0755); } @Override public void finishWrite(String path, OutputStream out) { IOTools.close(out); } @Override public void close() { if (sftpClient != null) { IOTools.close(sftpClient); } if (sshClient != null) { IOTools.close(sshClient); } } @Override public boolean move(String src, String dest, boolean overwrite) { String srcPath = getRealPath(src); String destPath = getRealPath(dest); if (!this.exist(srcPath)){ //源路径不存在 return false; } if (this.exist(destPath)){ if (!overwrite){ return false; } this.deleteFile(destPath); } try { SFTPClient client = getClient(); client.rename(srcPath, destPath); return true; } catch (IOException e) { return false; } } }