文章目录
- java的sftp传输
- sftp注意事项
- java smb传输
- smb注意事项
tips: 集成springboot与不集成springboot区别不大,springboot中无非是引入一个maven依赖 加一个@Component注解 , 默认是单例;
复制代码前 请先认真看注意事项
java的sftp传输
依赖:
<!-- sftp --><dependency><groupId>com.jcraft</groupId><artifactId>jsch</artifactId><version>0.1.49</version></dependency>
核心代码:
import com.jcraft.jsch.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.util.Properties;
import java.util.Vector;@Slf4j
@Component
public class SftpUtils {private Session sshSession;private ChannelSftp sftp;/*** 连接sftp服务器** @param host* @param port* @param username* @param password* @return* @throws Exception*/public ChannelSftp connect(String host, int port, String username, String password) throws Exception {JSch jsch = new JSch();sshSession = jsch.getSession(username, host, port);log.debug("Session created.");sshSession.setPassword(password);Properties sshConfig = new Properties();sshConfig.put("StrictHostKeyChecking", "no");sshSession.setConfig(sshConfig);sshSession.connect();log.debug("Session connected.");log.debug("Opening Channel.");Channel channel = sshSession.openChannel("sftp");channel.connect();sftp = (ChannelSftp) channel;log.debug("Connected to " + host + ".");return sftp;}/*** 连接sftp服务器** @param host* @param port* @param username* @param privateKey* @param passphrase* @return* @throws Exception*/public ChannelSftp connect(String host, int port, String username, String privateKey, String passphrase) throws Exception {JSch jsch = new JSch();//设置密钥和密码if (!StringUtils.isEmpty(privateKey)) {if (!StringUtils.isEmpty(passphrase)) {//设置带口令的密钥jsch.addIdentity(privateKey, passphrase);} else {//设置不带口令的密钥jsch.addIdentity(privateKey);}}sshSession = jsch.getSession(username, host, port);log.debug("Session created.");Properties sshConfig = new Properties();sshConfig.put("StrictHostKeyChecking", "no");sshSession.setConfig(sshConfig);sshSession.connect();log.debug("Session connected.");log.debug("Opening Channel.");Channel channel = sshSession.openChannel("sftp");channel.connect();sftp = (ChannelSftp) channel;log.debug("Connected to " + host + ".");return sftp;}public void portForwardingL(int lport, String rhost, int rport) throws Exception {int assinged_port = sshSession.setPortForwardingL(lport, rhost, rport);System.out.println("localhost:" + assinged_port + " -> " + rhost + ":" + rport);}/*** 断开连接*/public void disconnect() {if (sftp != null) sftp.disconnect();if (sshSession != null) sshSession.disconnect();}/*** 上传文件** @param directory 服务器的目录路径* @param uploadFile 要上传的文件路径* <p>* File path = new File(ResourceUtils.getURL("classpath:").getPath());* path.getAbsolutePath() : 相对路径 即class目录下*/public void upload(String directory, String uploadFile) throws Exception {sftp.cd(directory);File file = new File(uploadFile);sftp.put(new FileInputStream(file), file.getName());}/*** 上传文件** @param directory 服务器的目录路径* @param file 要上传的文件 例如 new File("Dockerfile") 是springboot项目根目录下的Dockerfile文件* @throws Exception*/public void upload(String directory, File file) throws Exception {sftp.cd(directory);sftp.put(new FileInputStream(file), file.getName());log.info("upload file " + file.getAbsolutePath() + " to host " + sshSession.getHost());}//利用流上传文件 fileNamepublic void uploadFileInputStream(MultipartFile file, String directory, String fileName) throws Exception {sftp.cd(directory);sftp.put(file.getInputStream(), fileName);}public void uploadDir(File src, String dst) throws Exception {if (!exist(dst)) {sftp.mkdir(dst);}if (src.isFile()) {upload(dst, src);} else {for (File file : src.listFiles()) {if (file.isDirectory()) {uploadDir(file, dst + "/" + file.getName());}upload(dst, file);}}}/*** 目录是否查找** @param path* @return* @throws SftpException*/public boolean exist(String path) throws SftpException {String pwd = sftp.pwd();try {sftp.cd(path);} catch (SftpException e) {if (e.id == ChannelSftp.SSH_FX_NO_SUCH_FILE) {return false;} else {throw e;}} finally {sftp.cd(pwd);}return true;}/*** 下载文件** @param directory 服务器目录* @param downloadFile 要下载的文件名* @param saveFile 输出文件名* @throws Exception*/public void download(String directory, String downloadFile, String saveFile) throws Exception {try {sftp.cd(directory);File file = new File(saveFile);sftp.get(downloadFile, new FileOutputStream(file));} catch (SftpException e) {e.printStackTrace();} catch (FileNotFoundException e) {e.printStackTrace();} finally {disconnect();}}/*** 下载文件** @param directory* @param downloadFile* @param saveFile* @throws Exception*/public void download(String directory, String downloadFile, File saveFile) throws Exception {try {sftp.cd(directory);sftp.get(downloadFile, new FileOutputStream(saveFile));System.out.println("download file " + directory + "/" + downloadFile + " from host " + sshSession.getHost());} catch (SftpException e) {e.printStackTrace();} catch (FileNotFoundException e) {e.printStackTrace();} finally {disconnect();}}/*** 下载文件** @param src* @param dst* @throws Exception*/@SuppressWarnings("unchecked")public void downloadDir(String src, File dst) throws Exception {try {sftp.cd(src);} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();}dst.mkdirs();Vector<ChannelSftp.LsEntry> files = sftp.ls(src);for (ChannelSftp.LsEntry lsEntry : files) {if (lsEntry.getFilename().equals(".") || lsEntry.getFilename().equals("..")) {continue;}if (lsEntry.getLongname().startsWith("d")) {downloadDir(src + "/" + lsEntry.getFilename(), new File(dst, lsEntry.getFilename()));} else {download(src, lsEntry.getFilename(), new File(dst, lsEntry.getFilename()));}}}/*** 删除文件** @param directory* @param deleteFile* @throws SftpException*/public void delete(String directory, String deleteFile) throws SftpException {sftp.cd(directory);sftp.rm(deleteFile);}/*** 列出目录下的文件** @param directory* @return* @throws SftpException*/public Vector listFiles(String directory) throws SftpException {return sftp.ls(directory);}public Session getSshSession() {return sshSession;}public ChannelSftp getSftp() {return sftp;}}
这个使用比较简单 也没有什么歧义 使用示例就不再写了
sftp注意事项
注: ftp和sftp是有区别的 ,linux中 ftp默认21端口 sftp默认是22端口,sftp传输加密 安全 所以效率较低,ftp传输不安全 所以效率较高, 本文讨论的是sftp 两种协议jar包引用不同。
java smb传输
依赖:
<!-- samba 共享文件夹 --><dependency><groupId>jcifs</groupId><artifactId>jcifs</artifactId><version>1.3.17</version></dependency>
简单封装了一个model类
model类代码:
/*** smb传输 model类* SMB地址写法:smb://用户名:密码@远程ip/地址/(或有无文件名)(注:如只获取文件夹后缀一定有“/”)* <p>*/
@Data
@EqualsAndHashCode
public class SMBConfig implements Serializable {/*** 服务器ip*/private String smbIp;/*** 服务器账号*/private String smbUser;/*** 服务器密码*/private String smbPwd;/*** 文件路径 在共享文件夹中的路径 (不带计算机名称)*/private String smbPath;/*** 文件名*/private String smbFile;/*** 输入流*/private InputStream is;/*** 输出流*/private OutputStream os;public SMBConfig() {}}
核心代码:
// import SMBConfig类路径;
import jcifs.UniAddress;
import jcifs.smb.NtlmPasswordAuthentication;
import jcifs.smb.SmbFile;
import jcifs.smb.SmbSession;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;import java.io.*;@Component
@Slf4j
public class SMBUtils {/*** 往samba上传文件** @param url 服务器IP地址* @param userName 用户登录名* @param password 用户登录密码* @param storePath 服务器文件存储路径* @param fileName 服务器文件存储名称* @param is 文件输入流* @return true:上传成功* <p>* false:上传失败*/public static boolean storeFile(String url, String userName, String password, String storePath, String fileName, InputStream is) {BufferedInputStream bf = null;OutputStream os = null;boolean result = false;try {UniAddress ua = UniAddress.getByName(url);NtlmPasswordAuthentication auth = new NtlmPasswordAuthentication(url, userName, password);SmbSession.logon(ua, auth);SmbFile sf = new SmbFile("smb://" + url + storePath + "/" + fileName, auth);sf.connect();SmbFile sffolder = new SmbFile("smb://" + url + storePath, auth);if (!sffolder.exists())sffolder.mkdirs();bf = new BufferedInputStream(is);os = sf.getOutputStream();byte[] bt = new byte[1024];int n = bf.read(bt);while (n != -1) {os.write(bt, 0, n);os.flush();n = bf.read(bt);}result = true;} catch (Exception e) {log.error(e.getMessage(), e);} finally {try {if (bf != null)bf.close();if (os != null)os.close();} catch (IOException e) {log.error(e.getMessage(), e);}}return result;}/*** 从samba下载文件** @param url 服务器IP地址* @param userName 用户登录名* @param password 用户登录密码* @param remotePath 服务器文件存储路径* @param fileName 服务器文件存储名称* @param os 文件输出流* @return true:下载成功* <p>* false:下载失败*/public static boolean retrieveFile(String url, String userName, String password, String remotePath, String fileName, OutputStream os) {boolean result = false;BufferedInputStream bf = null;try {UniAddress ua = UniAddress.getByName(url);NtlmPasswordAuthentication auth = new NtlmPasswordAuthentication(url, userName, password);SmbSession.logon(ua, auth);SmbFile sf = new SmbFile("smb://" + url + remotePath + "/" + fileName, auth);if (sf.exists()) {bf = new BufferedInputStream(sf.getInputStream());byte[] bt = new byte[1024];int n = bf.read(bt);while (n != -1) {os.write(bt, 0, n);os.flush();n = bf.read(bt);}result = true;}} catch (Exception e) {log.error(e.getMessage(), e);} finally {try {if (bf != null)bf.close();if (os != null)os.close();} catch (IOException e) {log.error(e.getMessage(), e);}}return result;}/*** 从samba删除文件** @param url 服务器IP地址* @param userName 用户登录名* @param password 用户登录密码* @param remotePath 服务器文件存储路径* @param fileName 服务器文件存储名称* @return true:删除成功* <p>* false:删除失败*/public static boolean deleteFile(String url, String userName, String password, String remotePath, String fileName) {boolean result = false;try {UniAddress ua = UniAddress.getByName(url);NtlmPasswordAuthentication auth = new NtlmPasswordAuthentication(url, userName, password);SmbSession.logon(ua, auth);SmbFile sf = new SmbFile("smb://" + url + remotePath + "/" + fileName, auth);sf.delete();result = true;} catch (Exception e) {log.error(e.getMessage(), e);}return result;}/*** 往samba上传文件** @param smbConfig* @return*/public static boolean storeFile(SMBConfig smbConfig) {return storeFile(smbConfig.getSmbIp(), smbConfig.getSmbUser(), smbConfig.getSmbPwd(), smbConfig.getSmbPath(), smbConfig.getSmbFile(), smbConfig.getIs());}/*** 从samba下载文件** @param smbConfig* @return*/public static boolean retrieveFile(SMBConfig smbConfig) {return retrieveFile(smbConfig.getSmbIp(), smbConfig.getSmbUser(), smbConfig.getSmbPwd(), smbConfig.getSmbPath(), smbConfig.getSmbFile(), smbConfig.getOs());}}
使用示例:
SMBConfig smbConfig = new SMBConfig();smbConfig.setSmbIp("192.168.1.1");smbConfig.setSmbPwd("123456");smbConfig.setSmbUser("admin");// 路径smbConfig.setSmbPath("/test");// 上传后的文件名叫这个smbConfig.setSmbFile("pom");// 将springboot项目中根目录的pom.xml文件上传smbConfig.setIs(new FileInputStream("pom.xml"));// 上传storeFile(smbConfig);
注: smbPath 例如在共享文件夹中 路径为test 就写/test ,不用加上下图马赛克位置的计算机名
smb注意事项
smb1.0和2.0方式有差异 依赖也不同,本文是基于smb1.0协议的,需要windows服务器中开启,win10/win11中 在启用或关闭windows功能中开启
windows server中 在powerShell用命令开启:
Set-SmbServerConfiguration -EnableSMB1Protocol $true
如果windows服务器没有账号密码,需要先设置;
如果共享功能没有开启 需要先开启