@Component
public class FileUploadUtil {

@Value("${remoteServer.url}")
private String url;

@Value("${remoteServer.password}")
private String passWord;

@Value("${remoteServer.username}")
private String userName;
@Value("${remoteServer.targetPath}")
private String targetPath;

@Async
public ResultEntity uploadFile(File file) throws Exception{
ScpConnectEntity scpConnectEntity=new ScpConnectEntity();
scpConnectEntity.setTargetPath(targetPath);
scpConnectEntity.setUrl(url);
scpConnectEntity.setPassWord(passWord);
scpConnectEntity.setUserName(userName);
String fileName = file.getName();
System.out.println("文件名称:"+fileName);
String remoteFileName=fileName;
String code = null;
String message = null;
try {
if (file == null || !file.exists()) {
throw new IllegalArgumentException("请确保上传文件不为空且存在!");
}
if(remoteFileName==null || "".equals(remoteFileName.trim())){
throw new IllegalArgumentException("远程服务器新建文件名不能为空!");
}
remoteUploadFile(scpConnectEntity, file, remoteFileName);
code = "ok";
message = remoteFileName;
} catch (IllegalArgumentException e) {
code = "Exception";
message = e.getMessage();
} catch (JSchException e) {
code = "Exception";
message = e.getMessage();
} catch (IOException e) {
code = "Exception";
message = e.getMessage();
} catch (Exception e) {
throw e;
} catch (Error e) {
code = "Error";
message = e.getMessage();
}

return new ResultEntity(code, message, null,remoteFileName);
}


private void remoteUploadFile(ScpConnectEntity scpConnectEntity, File file,
String remoteFileName) throws JSchException, IOException {

Connection connection = null;
Session session = null;
SCPOutputStream scpo = null;
FileInputStream fis = null;

try {
createDir(scpConnectEntity);
}catch (JSchException e) {
throw e;
}

try {
String url = scpConnectEntity.getUrl();
connection = new Connection(url);
connection.connect();

if(!connection.authenticateWithPassword(scpConnectEntity.getUserName(),scpConnectEntity.getPassWord())){
throw new RuntimeException("SSH连接服务器失败");
}
session = connection.openSession();

SCPClient scpClient = connection.createSCPClient();

scpo = scpClient.put(remoteFileName, file.length(), scpConnectEntity.getTargetPath(), "0666");
fis = new FileInputStream(file);

byte[] buf = new byte[1024];
int hasMore = fis.read(buf);

while(hasMore != -1){
scpo.write(buf);
hasMore = fis.read(buf);
}
} catch (IOException e) {
throw new IOException("SSH上传文件至服务器出错"+e.getMessage());
}finally {
if(null != fis){
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(null != scpo){
try {
scpo.flush();
// scpo.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(null != session){
session.close();
}
if(null != connection){
connection.close();
}
}
}


private boolean createDir(ScpConnectEntity scpConnectEntity ) throws JSchException {

JSch jsch = new JSch();
com.jcraft.jsch.Session sshSession = null;
Channel channel= null;
try {
sshSession = jsch.getSession(scpConnectEntity.getUserName(), scpConnectEntity.getUrl(), 22);
sshSession.setPassword(scpConnectEntity.getPassWord());
sshSession.setConfig("StrictHostKeyChecking", "no");
sshSession.connect();
channel = sshSession.openChannel("sftp");
channel.connect();
} catch (JSchException e) {
e.printStackTrace();
throw new JSchException("SFTP连接服务器失败"+e.getMessage());
}
ChannelSftp channelSftp=(ChannelSftp) channel;
if (isDirExist(scpConnectEntity.getTargetPath(),channelSftp)) {
channel.disconnect();
channelSftp.disconnect();
sshSession.disconnect();
return true;
}else {
String pathArry[] = scpConnectEntity.getTargetPath().split("/");
StringBuffer filePath=new StringBuffer("/");
for (String path : pathArry) {
if (path.equals("")) {
continue;
}
filePath.append(path + "/");
try {
if (isDirExist(filePath.toString(),channelSftp)) {
channelSftp.cd(filePath.toString());
} else {
// 建立目录
channelSftp.mkdir(filePath.toString());
// 进入并设置为当前目录
channelSftp.cd(filePath.toString());
}
} catch (SftpException e) {
e.printStackTrace();
throw new JSchException("SFTP无法正常操作服务器"+e.getMessage());
}
}
}
channel.disconnect();
channelSftp.disconnect();
sshSession.disconnect();
return true;
}

private boolean isDirExist(String directory,ChannelSftp channelSftp) {
boolean isDirExistFlag = false;
try {
SftpATTRS sftpATTRS = channelSftp.lstat(directory);
isDirExistFlag = true;
return sftpATTRS.isDir();
} catch (Exception e) {
if (e.getMessage().toLowerCase().equals("no such file")) {
isDirExistFlag = false;
}
}
return isDirExistFlag;
}


public class ScpConnectEntity {
private String userName;
private String passWord;
private String url;
private String targetPath;

public String getTargetPath() {
return targetPath;
}

public void setTargetPath(String targetPath) {
this.targetPath = targetPath;
}

public String getUserName() {
return userName;
}

public void setUserName(String userName) {
this.userName = userName;
}

public String getPassWord() {
return passWord;
}

public void setPassWord(String passWord) {
this.passWord = passWord;
}

public String getUrl() {
return url;
}

public void setUrl(String url) {
this.url = url;
}

}

public class ResultEntity {
private String code;

private String message;

private File file;

private String fileName;

public String getCode() {
return code;
}

public void setCode(String code) {
this.code = code;
}

public String getMessage() {
return message;
}

public void setMessage(String message) {
this.message = message;
}

public File getFile() {
return file;
}

public void setFile(File file) {
this.file = file;
}

public String getFileName() {
return fileName;
}

public void setFileName(String fileName) {
this.fileName = fileName;
}

public ResultEntity(String code, String message, File file, String fileName) {
this.code = code;
this.message = message;
this.file = file;
this.fileName = fileName;
}
}