sftp 下载实现
使用零拷贝技术优化合并分块的功能
This commit is contained in:
@@ -16,16 +16,19 @@
|
||||
package com.arialyy.aria.sftp;
|
||||
|
||||
import android.text.TextUtils;
|
||||
import com.arialyy.aria.util.ALog;
|
||||
import com.arialyy.aria.core.FtpUrlEntity;
|
||||
import com.arialyy.aria.core.IdEntity;
|
||||
import com.arialyy.aria.util.CommonUtil;
|
||||
import com.jcraft.jsch.ChannelExec;
|
||||
import com.arialyy.aria.util.FileUtil;
|
||||
import com.jcraft.jsch.JSch;
|
||||
import com.jcraft.jsch.JSchException;
|
||||
import com.jcraft.jsch.Session;
|
||||
import java.io.BufferedReader;
|
||||
import com.jcraft.jsch.UserInfo;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
@@ -35,166 +38,137 @@ import java.util.Properties;
|
||||
*/
|
||||
public class SFtpUtil {
|
||||
private final String TAG = CommonUtil.getClassName(getClass());
|
||||
/**
|
||||
* 用于执行命令
|
||||
*/
|
||||
public static final String CMD_TYPE_EXEC = "exec";
|
||||
/**
|
||||
* 用于处理文件
|
||||
*/
|
||||
public static final String CMD_TYPE_SFTP = "sftp";
|
||||
private String ip, userName, password;
|
||||
private int port;
|
||||
private Session session;
|
||||
private boolean isLogin = false;
|
||||
|
||||
private static SFtpUtil INSTANCE;
|
||||
|
||||
private SFtpUtil() {
|
||||
createClient();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建客户端
|
||||
*/
|
||||
private void createClient() {
|
||||
JSch jSch = new JSch();
|
||||
try {
|
||||
if (TextUtils.isEmpty(userName)) {
|
||||
session = jSch.getSession(userName, ip, port);
|
||||
} else {
|
||||
session = jSch.getSession(ip);
|
||||
public synchronized static SFtpUtil getInstance() {
|
||||
if (INSTANCE == null) {
|
||||
synchronized (SFtpUtil.class) {
|
||||
INSTANCE = new SFtpUtil();
|
||||
}
|
||||
if (!TextUtils.isEmpty(password)) {
|
||||
session.setPassword(password);
|
||||
}
|
||||
Properties config = new Properties();
|
||||
config.put("StrictHostKeyChecking", "no");
|
||||
session.setConfig(config);// 为Session对象设置properties
|
||||
session.setTimeout(3000);// 设置超时
|
||||
login();
|
||||
isLogin = true;
|
||||
} catch (JSchException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行登录
|
||||
*/
|
||||
public Session login() {
|
||||
try {
|
||||
session.connect(); // 通过Session建立连接
|
||||
} catch (JSchException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return session;
|
||||
}
|
||||
|
||||
/**
|
||||
* 登出
|
||||
*/
|
||||
public void logout() {
|
||||
if (session != null) {
|
||||
session.disconnect();
|
||||
}
|
||||
isLogin = false;
|
||||
}
|
||||
|
||||
public Session getSession() {
|
||||
return session;
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行命令
|
||||
* 创建jsch 的session
|
||||
*
|
||||
* @param cmd sftp命令
|
||||
* @param threadId 线程id,默认0
|
||||
* @throws JSchException
|
||||
* @throws UnsupportedEncodingException
|
||||
*/
|
||||
public void execCommand(String cmd) {
|
||||
if (TextUtils.isEmpty(cmd)) {
|
||||
ALog.e(TAG, "命令为空");
|
||||
return;
|
||||
}
|
||||
if (!isLogin) {
|
||||
ALog.e(TAG, "没有登录");
|
||||
return;
|
||||
}
|
||||
ChannelExec channel = null;
|
||||
try {
|
||||
channel = (ChannelExec) session.openChannel(CMD_TYPE_EXEC);
|
||||
channel.setCommand(cmd);
|
||||
channel.connect();
|
||||
String rst = getResult(channel.getInputStream());
|
||||
public Session getSession(FtpUrlEntity entity, int threadId) throws JSchException,
|
||||
UnsupportedEncodingException {
|
||||
|
||||
ALog.i(TAG, String.format("result: %s", rst));
|
||||
JSch jSch = new JSch();
|
||||
|
||||
IdEntity idEntity = entity.idEntity;
|
||||
|
||||
if (idEntity.prvKey != null) {
|
||||
if (idEntity.pubKey == null) {
|
||||
jSch.addIdentity(idEntity.prvKey,
|
||||
entity.password == null ? null : idEntity.prvPass.getBytes("UTF-8"));
|
||||
} else {
|
||||
jSch.addIdentity(idEntity.prvKey, idEntity.pubKey,
|
||||
entity.password == null ? null : idEntity.prvPass.getBytes("UTF-8"));
|
||||
}
|
||||
}
|
||||
|
||||
setknowHost(jSch, entity);
|
||||
|
||||
Session session;
|
||||
if (TextUtils.isEmpty(entity.user)) {
|
||||
session = jSch.getSession(null, entity.hostName, Integer.parseInt(entity.port));
|
||||
} else {
|
||||
session = jSch.getSession(entity.user, entity.hostName, Integer.parseInt(entity.port));
|
||||
}
|
||||
if (!TextUtils.isEmpty(entity.password)) {
|
||||
session.setPassword(entity.password);
|
||||
}
|
||||
Properties config = new Properties();
|
||||
|
||||
// 不检查公钥,需要在connect之前配置,但是不安全,no 模式会自动将配对信息写入know_host文件
|
||||
config.put("StrictHostKeyChecking", "no");
|
||||
session.setConfig(config);// 为Session对象设置properties
|
||||
session.setTimeout(3000);// 设置超时
|
||||
session.setIdentityRepository(jSch.getIdentityRepository());
|
||||
session.connect();
|
||||
SFtpSessionManager.getInstance().addSession(session, threadId);
|
||||
return session;
|
||||
}
|
||||
|
||||
private void setknowHost(JSch jSch, FtpUrlEntity entity) throws JSchException {
|
||||
IdEntity idEntity = entity.idEntity;
|
||||
if (idEntity.knowHost != null) {
|
||||
File knowFile = new File(idEntity.knowHost);
|
||||
if (!knowFile.exists()) {
|
||||
FileUtil.createFile(knowFile);
|
||||
}
|
||||
jSch.setKnownHosts(idEntity.knowHost);
|
||||
|
||||
//HostKeyRepository hkr = jSch.getHostKeyRepository();
|
||||
//hkr.add(new HostKey(entity.hostName, HostKey.SSHRSA, getPubKey(idEntity.pubKey)), new JschUserInfo());
|
||||
//
|
||||
//HostKey[] hks = hkr.getHostKey();
|
||||
//if (hks != null) {
|
||||
// System.out.println("Host keys in " + hkr.getKnownHostsRepositoryID());
|
||||
// for (int i = 0; i < hks.length; i++) {
|
||||
// HostKey hk = hks[i];
|
||||
// System.out.println(hk.getHost() + " " +
|
||||
// hk.getType() + " " +
|
||||
// hk.getFingerPrint(jSch));
|
||||
// }
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
||||
private byte[] getPubKey(String pubKeyPath) {
|
||||
try {
|
||||
File f = new File(pubKeyPath);
|
||||
FileInputStream fis = new FileInputStream(f);
|
||||
byte[] buf = new byte[(int) f.length()];
|
||||
int len = fis.read(buf);
|
||||
fis.close();
|
||||
return buf;
|
||||
} catch (FileNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
} catch (JSchException e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
if (channel != null) {
|
||||
channel.disconnect();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行命令后,获取服务器端返回的数据
|
||||
*
|
||||
* @return 服务器端返回的数据
|
||||
*/
|
||||
private String getResult(InputStream in) throws IOException {
|
||||
if (in == null){
|
||||
ALog.e(TAG, "输入流为空");
|
||||
private static class JschUserInfo implements UserInfo {
|
||||
|
||||
@Override public String getPassphrase() {
|
||||
return null;
|
||||
}
|
||||
StringBuilder sb = new StringBuilder();
|
||||
BufferedReader isr = new BufferedReader(new InputStreamReader(in));
|
||||
String line;
|
||||
while ((line = isr.readLine()) != null) {
|
||||
sb.append(line);
|
||||
}
|
||||
in.close();
|
||||
isr.close();
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
private String ip, userName, password;
|
||||
private int port = 22;
|
||||
|
||||
public Builder setIp(String ip) {
|
||||
this.ip = ip;
|
||||
return this;
|
||||
@Override public String getPassword() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Builder setUserName(String userName) {
|
||||
this.userName = userName;
|
||||
return this;
|
||||
@Override public boolean promptPassword(String message) {
|
||||
System.out.println(message);
|
||||
return true;
|
||||
}
|
||||
|
||||
public Builder setPassword(String password) {
|
||||
this.password = password;
|
||||
return this;
|
||||
@Override public boolean promptPassphrase(String message) {
|
||||
System.out.println(message);
|
||||
return false;
|
||||
}
|
||||
|
||||
public Builder setPort(int port) {
|
||||
this.port = port;
|
||||
return this;
|
||||
@Override public boolean promptYesNo(String message) {
|
||||
System.out.println(message);
|
||||
return false;
|
||||
}
|
||||
|
||||
public SFtpUtil build() {
|
||||
SFtpUtil login = new SFtpUtil();
|
||||
login.ip = ip;
|
||||
login.userName = userName;
|
||||
login.password = password;
|
||||
login.port = port;
|
||||
if (TextUtils.isEmpty(ip)) {
|
||||
throw new IllegalArgumentException("ip不能为空");
|
||||
}
|
||||
if (port < 0 || port > 65534) {
|
||||
throw new IllegalArgumentException("端口错误");
|
||||
}
|
||||
return login;
|
||||
@Override public void showMessage(String message) {
|
||||
System.out.println(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user