|
|
@@ -0,0 +1,579 @@
|
|
|
+package com.uas.util;
|
|
|
+
|
|
|
+import com.jcraft.jsch.*;
|
|
|
+import org.apache.commons.io.IOUtils;
|
|
|
+import org.slf4j.Logger;
|
|
|
+import org.slf4j.LoggerFactory;
|
|
|
+
|
|
|
+import java.io.*;
|
|
|
+import java.util.*;
|
|
|
+
|
|
|
+
|
|
|
+/**
|
|
|
+ * 类说明 sftp工具类
|
|
|
+ */
|
|
|
+public class SFTPUtil {
|
|
|
+ private transient Logger log = LoggerFactory.getLogger(this.getClass());
|
|
|
+
|
|
|
+ private ChannelSftp sftp;
|
|
|
+
|
|
|
+ private Session session;
|
|
|
+ /** SFTP 登录用户名*/
|
|
|
+ private String username;
|
|
|
+ /** SFTP 登录密码*/
|
|
|
+ private String password;
|
|
|
+ /** 私钥 */
|
|
|
+ private String privateKey;
|
|
|
+ /** SFTP 服务器地址IP地址*/
|
|
|
+ private String host;
|
|
|
+ /** SFTP 端口*/
|
|
|
+ private int port;
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 构造基于密码认证的sftp对象
|
|
|
+ */
|
|
|
+ public SFTPUtil(String username, String password, String host, int port) {
|
|
|
+ this.username = username;
|
|
|
+ this.password = password;
|
|
|
+ this.host = host;
|
|
|
+ this.port = port;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 构造基于秘钥认证的sftp对象
|
|
|
+ */
|
|
|
+ public SFTPUtil(String username, String host, int port, String privateKey) {
|
|
|
+ this.username = username;
|
|
|
+ this.host = host;
|
|
|
+ this.port = port;
|
|
|
+ this.privateKey = privateKey;
|
|
|
+ }
|
|
|
+
|
|
|
+ public SFTPUtil(){}
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 连接sftp服务器
|
|
|
+ */
|
|
|
+ public boolean login() throws JSchException {
|
|
|
+ boolean result = false;
|
|
|
+ JSch jsch = new JSch();
|
|
|
+ if (privateKey != null) {
|
|
|
+ jsch.addIdentity(privateKey);// 设置私钥
|
|
|
+ }
|
|
|
+
|
|
|
+ session = jsch.getSession(username, host, port);
|
|
|
+
|
|
|
+ if (password != null) {
|
|
|
+ session.setPassword(password);
|
|
|
+ }
|
|
|
+ Properties config = new Properties();
|
|
|
+ config.put("StrictHostKeyChecking", "no");
|
|
|
+
|
|
|
+ session.setConfig(config);
|
|
|
+ session.connect();
|
|
|
+
|
|
|
+ Channel channel = session.openChannel("sftp");
|
|
|
+ channel.connect();
|
|
|
+
|
|
|
+ sftp = (ChannelSftp) channel;
|
|
|
+ result = true;
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 关闭连接 server
|
|
|
+ */
|
|
|
+ public void logout(){
|
|
|
+ if (sftp != null) {
|
|
|
+ if (sftp.isConnected()) {
|
|
|
+ sftp.disconnect();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (session != null) {
|
|
|
+ if (session.isConnected()) {
|
|
|
+ session.disconnect();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 将输入流的数据上传到sftp作为文件。文件完整路径=basePath+directory
|
|
|
+ * @param basePath 服务器的基础路径
|
|
|
+ * @param directory 上传到该目录
|
|
|
+ * @param sftpFileName sftp端文件名
|
|
|
+ * @param input 输入流
|
|
|
+ */
|
|
|
+ public boolean upload(String basePath,String directory, String sftpFileName, InputStream input) throws SftpException{
|
|
|
+ boolean flag =false;
|
|
|
+ try {
|
|
|
+ sftp.cd(basePath);
|
|
|
+ sftp.cd(directory);
|
|
|
+ flag = true;
|
|
|
+ sftp.put(input, sftpFileName); //上传文件
|
|
|
+ } catch (SftpException e) {
|
|
|
+ //目录不存在,则创建文件夹
|
|
|
+ /* String [] dirs=directory.split("/");
|
|
|
+ String tempPath=basePath;
|
|
|
+ for(String dir:dirs){
|
|
|
+ if(null== dir || "".equals(dir)) continue;
|
|
|
+ tempPath+="/"+dir;
|
|
|
+ try{
|
|
|
+ sftp.cd(tempPath);
|
|
|
+ }catch(SftpException ex){
|
|
|
+ sftp.mkdir(tempPath);
|
|
|
+ sftp.cd(tempPath);
|
|
|
+ }
|
|
|
+ }*/
|
|
|
+ flag = false;
|
|
|
+ }
|
|
|
+ return flag;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 下载文件。
|
|
|
+ * @param directory 下载目录
|
|
|
+ * @param downloadFile 下载的文件
|
|
|
+ * @param saveFile 存在本地的路径
|
|
|
+ */
|
|
|
+ public void download(String directory, String downloadFile, String saveFile) throws SftpException, FileNotFoundException{
|
|
|
+ if (directory != null && !"".equals(directory)) {
|
|
|
+ sftp.cd(directory);
|
|
|
+ }
|
|
|
+ File file = new File(saveFile);
|
|
|
+ sftp.get(downloadFile, new FileOutputStream(file));
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 下载文件
|
|
|
+ * @param directory 下载目录
|
|
|
+ * @param downloadFile 下载的文件名
|
|
|
+ * @return 字节数组
|
|
|
+ */
|
|
|
+ public byte[] download(String directory, String downloadFile) throws SftpException, IOException{
|
|
|
+ if (directory != null && !"".equals(directory)) {
|
|
|
+ sftp.cd(directory);
|
|
|
+ }
|
|
|
+ InputStream is = sftp.get(downloadFile);
|
|
|
+
|
|
|
+ byte[] fileData = IOUtils.toByteArray(is);
|
|
|
+
|
|
|
+ return fileData;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 删除文件
|
|
|
+ * @param directory 要删除文件所在目录
|
|
|
+ * @param deleteFile 要删除的文件
|
|
|
+ */
|
|
|
+ public void delete(String directory, String deleteFile) throws SftpException{
|
|
|
+ sftp.cd(directory);
|
|
|
+ sftp.rm(deleteFile);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 列出目录下的文件
|
|
|
+ * @param
|
|
|
+ * @param directory 要列出的目录
|
|
|
+ */
|
|
|
+ public List<File> listFiles(String directory) throws SftpException {
|
|
|
+ Vector<ChannelSftp.LsEntry> list = sftp.ls(directory);
|
|
|
+ List<File> files = new ArrayList<>();
|
|
|
+ if (list.size()>0&&list!=null) {
|
|
|
+ for (ChannelSftp.LsEntry entry : list) {
|
|
|
+ if (!".".equals(entry.getFilename()) && !"..".equals(entry.getFilename())) {
|
|
|
+ File file = new File("/"+directory+"/");
|
|
|
+ files.add(file);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return files;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 下载流
|
|
|
+ * @param
|
|
|
+ * @param directory 下载目录
|
|
|
+ */
|
|
|
+ public List<File> download(String directory) {
|
|
|
+ try {
|
|
|
+ Vector<ChannelSftp.LsEntry> list = sftp.ls(directory);
|
|
|
+ List<File> ls = new ArrayList<File>();
|
|
|
+ if (list.size()>0&&list!=null) {
|
|
|
+ for (ChannelSftp.LsEntry entry : list) {
|
|
|
+ if (!".".equals(entry.getFilename()) && !"..".equals(entry.getFilename())) {
|
|
|
+ if (entry.getFilename().endsWith(".xml")) {
|
|
|
+ InputStream is = sftp.get(directory+"/"+entry.getFilename());
|
|
|
+ File temp= File.createTempFile(entry.getFilename(),"");
|
|
|
+ OutputStream os = new FileOutputStream(temp);
|
|
|
+ int bytesRead = 0;
|
|
|
+ byte[] buffer = new byte[102400];
|
|
|
+ while ((bytesRead = is.read(buffer, 0, 102400)) != -1) {
|
|
|
+ os.write(buffer, 0, bytesRead);
|
|
|
+ }
|
|
|
+ is.close();
|
|
|
+ os.close();
|
|
|
+ ls.add(temp);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return ls;
|
|
|
+ } catch (Exception e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 根目录
|
|
|
+ *
|
|
|
+ * @return String
|
|
|
+ */
|
|
|
+ private String homeDir()
|
|
|
+ {
|
|
|
+ try {
|
|
|
+ return sftp.getHome();
|
|
|
+ } catch (Exception e) {
|
|
|
+ return "/";
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public String currentDir()
|
|
|
+ {
|
|
|
+ try {
|
|
|
+ String pwd = sftp.pwd();
|
|
|
+ System.err.println(pwd);
|
|
|
+ return pwd;
|
|
|
+
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("failed to get current dir", e);
|
|
|
+ return homeDir();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 切换工作目录
|
|
|
+ *
|
|
|
+ * @param pathName 路径
|
|
|
+ * @return boolean
|
|
|
+ */
|
|
|
+ public boolean changeDir(String pathName)
|
|
|
+ {
|
|
|
+ if (pathName == null || pathName.trim().equals("")) {
|
|
|
+ log.debug("invalid pathName");
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ try {
|
|
|
+ sftp.cd(pathName.replaceAll("\\\\", "/"));
|
|
|
+ log.debug("directory successfully changed,current dir=" + sftp.pwd());
|
|
|
+ return true;
|
|
|
+ } catch (SftpException e) {
|
|
|
+ log.error("failed to change directory", e);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 列出当前目录下的文件及文件夹
|
|
|
+ *
|
|
|
+ * @param filter 过滤参数
|
|
|
+ * @return String[]
|
|
|
+ */
|
|
|
+ @SuppressWarnings("unchecked")
|
|
|
+ private String[] list(String filter)
|
|
|
+ {
|
|
|
+ Vector<ChannelSftp.LsEntry> list = null;
|
|
|
+ try {
|
|
|
+ //ls方法会返回两个特殊的目录,当前目录(.)和父目录(..)
|
|
|
+ list = sftp.ls(sftp.pwd());
|
|
|
+ } catch (SftpException e) {
|
|
|
+ log.error("can not list directory", e);
|
|
|
+ return new String[0];
|
|
|
+ }
|
|
|
+ List<String> resultList = new ArrayList<String>();
|
|
|
+ for (ChannelSftp.LsEntry entry : list) {
|
|
|
+ resultList.add(entry.getFilename());
|
|
|
+ }
|
|
|
+ return resultList.toArray(new String[0]);
|
|
|
+ }
|
|
|
+ /**
|
|
|
+ * 指定目录下文件名称列表
|
|
|
+ *
|
|
|
+ * @return String[]
|
|
|
+ */
|
|
|
+ public String[] lsFiles(String pathName) {
|
|
|
+ String currentDir = currentDir();
|
|
|
+ if (!changeDir(pathName)) {
|
|
|
+ return new String[0];
|
|
|
+ }
|
|
|
+ String[] result = list("File");
|
|
|
+ if (!changeDir(currentDir)) {
|
|
|
+ return new String[0];
|
|
|
+ }
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 批量下载文件
|
|
|
+ * @param remotePath:远程下载目录(以路径符号结束,可以为相对路径eg:/assess/sftp/jiesuan_2/2014/)
|
|
|
+ * @param localPath:本地保存目录(以路径符号结束,D:\Duansha\sftp\)
|
|
|
+ * @param fileFormat:下载文件格式(以特定字符开头,为空不做检验)
|
|
|
+ * @param fileEndFormat:下载文件格式(文件格式)
|
|
|
+ * @param del:下载后是否删除sftp文件
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ public List<String> batchDownLoadFile(String remotePath, String localPath,
|
|
|
+ String fileFormat, String fileEndFormat, boolean del)
|
|
|
+ {
|
|
|
+ List<String> filenames = new ArrayList<String>();
|
|
|
+ try
|
|
|
+ {
|
|
|
+ // connect();
|
|
|
+ Vector v = sftp.ls(remotePath);
|
|
|
+ // sftp.cd(remotePath);
|
|
|
+ if (v.size() > 0)
|
|
|
+ {
|
|
|
+ System.out.println("本次处理文件个数不为零,开始下载...fileSize=" + v.size());
|
|
|
+ Iterator it = v.iterator();
|
|
|
+ while (it.hasNext())
|
|
|
+ {
|
|
|
+ ChannelSftp.LsEntry entry = (ChannelSftp.LsEntry) it.next();
|
|
|
+ String filename = entry.getFilename();
|
|
|
+ SftpATTRS attrs = entry.getAttrs();
|
|
|
+ if (!attrs.isDir())
|
|
|
+ {
|
|
|
+ boolean flag = false;
|
|
|
+ String localFileName = localPath + filename;
|
|
|
+ fileFormat = fileFormat == null ? "" : fileFormat
|
|
|
+ .trim();
|
|
|
+ fileEndFormat = fileEndFormat == null ? ""
|
|
|
+ : fileEndFormat.trim();
|
|
|
+ // 三种情况
|
|
|
+ if (fileFormat.length() > 0 && fileEndFormat.length() > 0)
|
|
|
+ {
|
|
|
+ if (filename.startsWith(fileFormat) && filename.endsWith(fileEndFormat))
|
|
|
+ {
|
|
|
+ flag = downloadFile(remotePath, filename,localPath, filename);
|
|
|
+ if (flag)
|
|
|
+ {
|
|
|
+ filenames.add(localFileName);
|
|
|
+ if (flag && del)
|
|
|
+ {
|
|
|
+ //deleteSFTP(remotePath, filename);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else if (fileFormat.length() > 0 && "".equals(fileEndFormat))
|
|
|
+ {
|
|
|
+ if (filename.startsWith(fileFormat))
|
|
|
+ {
|
|
|
+ flag = downloadFile(remotePath, filename, localPath, filename);
|
|
|
+ if (flag)
|
|
|
+ {
|
|
|
+ filenames.add(localFileName);
|
|
|
+ if (flag && del)
|
|
|
+ {
|
|
|
+ //sftp.deleteSFTP(remotePath, filename);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else if (fileEndFormat.length() > 0 && "".equals(fileFormat))
|
|
|
+ {
|
|
|
+ if (filename.endsWith(fileEndFormat))
|
|
|
+ {
|
|
|
+ flag = downloadFile(remotePath, filename,localPath, filename);
|
|
|
+ if (flag)
|
|
|
+ {
|
|
|
+ filenames.add(localFileName);
|
|
|
+ if (flag && del)
|
|
|
+ {
|
|
|
+ //deleteSFTP(remotePath, filename);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ flag = downloadFile(remotePath, filename,localPath, filename);
|
|
|
+ if (flag)
|
|
|
+ {
|
|
|
+ filenames.add(localFileName);
|
|
|
+ if (flag && del)
|
|
|
+ {
|
|
|
+ //deleteSFTP(remotePath, filename);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (log.isInfoEnabled())
|
|
|
+ {
|
|
|
+ log.info("download file is success:remotePath=" + remotePath
|
|
|
+ + "and localPath=" + localPath + ",file size is"
|
|
|
+ + v.size());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ catch (SftpException e)
|
|
|
+ {
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+ finally
|
|
|
+ {
|
|
|
+ // this.disconnect();
|
|
|
+ }
|
|
|
+ return filenames;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 下载单个文件
|
|
|
+ * @param remotePath:远程下载目录(以路径符号结束)
|
|
|
+ * @param remoteFileName:下载文件名
|
|
|
+ * @param localPath:本地保存目录(以路径符号结束)
|
|
|
+ * @param localFileName:保存文件名
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ public boolean downloadFile(String remotePath, String remoteFileName,String localPath, String localFileName)
|
|
|
+ {
|
|
|
+ FileOutputStream fieloutput = null;
|
|
|
+ try
|
|
|
+ {
|
|
|
+ // sftp.cd(remotePath);
|
|
|
+ File file = new File(localPath + localFileName);
|
|
|
+ // mkdirs(localPath + localFileName);
|
|
|
+ fieloutput = new FileOutputStream(file);
|
|
|
+ sftp.get(remotePath + remoteFileName, fieloutput);
|
|
|
+ if (log.isInfoEnabled())
|
|
|
+ {
|
|
|
+ log.info("===DownloadFile:" + remoteFileName + " success from sftp.");
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ catch (FileNotFoundException e)
|
|
|
+ {
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+ catch (SftpException e)
|
|
|
+ {
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+ finally
|
|
|
+ {
|
|
|
+ if (null != fieloutput)
|
|
|
+ {
|
|
|
+ try
|
|
|
+ {
|
|
|
+ fieloutput.close();
|
|
|
+ }
|
|
|
+ catch (IOException e)
|
|
|
+ {
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ public Boolean rename(String name, String path) {
|
|
|
+ Boolean result = false;
|
|
|
+ try {
|
|
|
+ sftp.rename(name, path);
|
|
|
+ result = true;
|
|
|
+ } catch (SftpException e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ public boolean copyfile(String src, String path){
|
|
|
+ boolean result = false;
|
|
|
+ try {
|
|
|
+ InputStream tInputStream = null;
|
|
|
+
|
|
|
+ //tChannelSftp.mkdir(路径);
|
|
|
+ System.err.println(src);
|
|
|
+ tInputStream = sftp.get(src);
|
|
|
+
|
|
|
+ //拷贝读取到的文件流
|
|
|
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
|
|
+
|
|
|
+ byte[] buffer = new byte[1024];
|
|
|
+ int len;
|
|
|
+ while ((len = tInputStream.read(buffer)) > -1 ) {
|
|
|
+ baos.write(buffer, 0, len);
|
|
|
+ }
|
|
|
+ baos.flush();
|
|
|
+
|
|
|
+ InputStream nInputStream = new ByteArrayInputStream(baos.toByteArray());
|
|
|
+
|
|
|
+ sftp.put(nInputStream, path);
|
|
|
+
|
|
|
+ nInputStream.close();
|
|
|
+ baos.close();
|
|
|
+ tInputStream.close();
|
|
|
+ result = true;
|
|
|
+ }catch (Exception e){
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ //上传文件测试
|
|
|
+ /*public static void main(String[] args) throws SftpException, IOException {
|
|
|
+ SFTPUtil sftp = new SFTPUtil("wms_ufct", "ZjJ05GFV", "218.17.248.243", 45301);
|
|
|
+ //FtpUtil.connect("/To_XN_TEST/","218.4.62.135",21,"hsltoxn", "HtxN527%#");
|
|
|
+ try {
|
|
|
+ sftp.login();
|
|
|
+ } catch (JSchException e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+ /*File file = new File("C:\\Users\\usoft\\Downloads\\视图字段.xls");
|
|
|
+ InputStream is = new FileInputStream(file);
|
|
|
+
|
|
|
+ sftp.upload("/","To_XN_TEST", "uas_sftp.xls", is);*//*
|
|
|
+ //sftp.listFiles("/stockout/data/");
|
|
|
+ String ss = "/stockout/data/";
|
|
|
+ String addr = "D:/BaiduNetdiskDownload\\";
|
|
|
+ *//*String[] strings = sftp.lsFiles(ss);
|
|
|
+ for (String s:strings) {
|
|
|
+ System.err.println(s);
|
|
|
+ if (!".".equals(s)&&!"..".equals(s)) {
|
|
|
+ *//**//*sftp.download(ss,s,addr);
|
|
|
+ File file = new File(ss+s);
|
|
|
+ InputStream inputStream = new FileInputStream(file);*//**//*
|
|
|
+ boolean bat = sftp.downloadFile(ss, s, "D:/", s);
|
|
|
+ System.err.println(bat);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ sftp.logout();*//*
|
|
|
+ String sss = "GR_20190521121137B.xml";
|
|
|
+ String str = "\\stockout\\data\\";
|
|
|
+ String str1= str.replace("\\","/");
|
|
|
+ System.err.println(str);
|
|
|
+ *//*try {
|
|
|
+ InputStream in = new FileInputStream(sss);
|
|
|
+ SAXReader reader = new SAXReader();
|
|
|
+ Document doc = reader.read(in);
|
|
|
+ in.close();
|
|
|
+ Element element = doc.getRootElement();
|
|
|
+ System.err.println(element);
|
|
|
+ } catch (Exception e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ }*//*
|
|
|
+ //String src = "/stockout/data/GR_20190521121137B.xml";
|
|
|
+ //sftp.copyfile(src,"/stockout/backup/GR_20190521121137B.xml");
|
|
|
+ //sftp.logout();
|
|
|
+ boolean connect = FtpUtil.connect("From_QF", "112.74.205.182", 21, "YTZH02", "Ytzh)@2018");
|
|
|
+ System.err.println(connect);
|
|
|
+ FtpUtil.closeFtpClient(new FTPClient());
|
|
|
+ }*/
|
|
|
+}
|