【java】java sftp para acceder a carpetas, java smb para acceder a carpetas compartidas, filtrar por tiempo para encontrar archivos, integrar springboot

consejos: No hay mucha diferencia entre integrar springboot y no integrar springboot. Springboot no es más que introducir una dependencia maven y agregar una anotación @Component. El valor predeterminado es un singleton; lea atentamente las precauciones antes de copiar el
código

transferencia sftp java

confiar:

      <!-- sftp -->
        <dependency>
            <groupId>com.jcraft</groupId>
            <artifactId>jsch</artifactId>
            <version>0.1.49</version>
        </dependency>

Código central:


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());
    }

    //利用流上传文件 fileName
    public 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 block
            e.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;
    }

}



Este uso es relativamente simple y no hay ambigüedad, por lo que no escribiré más ejemplos.


lista de archivos de filtro sftp por tiempo

Este método está inspirado en el método de filtrado en smb1.0 y escrito mediante el estudio de la API del kit de herramientas Sftp.

Podemos ver el método ls(ruta) en ChannelSftp. De manera predeterminada, todas las entradas se agregan al vector y se llama al método ls(ruta, selector), por lo que podemos ver qué hay en la entrada: nombre de archivo: nombre de archivo
inserte la descripción de la imagen aquí
nombre
inserte la descripción de la imagen aquí
largo : nombre de archivo largo

Mira lo que hay dentro de los atributos:

inserte la descripción de la imagen aquí
Los estudiantes que están familiarizados con Linux pueden saber claramente qué es mtime. Por supuesto, incluso si no están familiarizados con él, pueden adivinar que es la abreviatura de tiempo de modificación de modifyTime. Dado que se proporcionan estos parámetros, podemos hacer un pequeño juicio y guarde la entrada cualificada en Vector.

El código es un poco inconsistente con nuestros hábitos. El método sftp(ls, selector) no tiene valor de retorno y recibe el valor en un vector definido externamente, y la unidad mtime es segundos, no milisegundos. Este detalle una vez hizo que los bloggers dudaran de la vida . .

el código se muestra a continuación:

(necesita copiar el código en la clase SftpUtils)

 /**
     * 列出(文件的最新修改时间)时间点之后的文件
     *
     * @param directory
     * @return
     * @throws SftpException
     */
    public Vector listFilesLaterThenTime(String directory, long time) throws SftpException {
    
    

        Vector vector = new Vector();

        sftp.ls(directory, new ChannelSftp.LsEntrySelector() {
    
    

            public int select(ChannelSftp.LsEntry entry) {
    
    
				// 很坑的点 atime和mtime的单位是秒 并非我们常用的毫秒
				// 从 getMtimeString()方法中的 mtime * 1000L 可以看出
                long mTime = entry.getAttrs().getMTime() * 1000L;
                if (mTime < time) {
    
    

                    vector.addElement(entry);
                }
                return 0;
            }
        });

        return vector;
    }

Notas sobre sftp

Nota: Hay una diferencia entre ftp y sftp. En Linux, ftp tiene como valor predeterminado el puerto 21 y sftp tiene como valor predeterminado el puerto 22. La eficiencia de cifrado de la transmisión sftp es baja y la eficiencia de la transmisión ftp es insegura. Este artículo analiza los dos protocolos. .


transmisión java smb1.0

confiar:


        <!-- samba 共享文件夹 -->
        <dependency>
            <groupId>jcifs</groupId>
            <artifactId>jcifs</artifactId>
            <version>1.3.17</version>
        </dependency>

Simplemente encapsula una clase modelo

Código de clase del modelo:

/**
 * 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() {
    
    

    }

}

Código central:


// 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());
    }


}

Ejemplo de uso:

	   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);

Nota: smbPath Por ejemplo, si la ruta es prueba en la carpeta compartida, escriba /prueba, sin agregar el nombre de la computadora de la ubicación del mosaico en la figura a continuación.
inserte la descripción de la imagen aquí


lista de archivos de filtro smb1.0 por tiempo

Tomemos un ejemplo de escenario: hay decenas de miles o más archivos en el servidor. Solicitamos al cliente que los procese de vez en cuando, por lo que la próxima vez que solicitemos al cliente, no necesitamos procesar los archivos que han sido procesados ​​antes.

Por lo tanto, cada solicitud debe registrar la última hora de modificación en este lote de archivos, y solo necesita procesar la hora de modificación mayor que la próxima vez.

Al observar la api en la clase SmbFile, encontramos que hay un parámetro SmbFileFilter en listFiles, lo que significa que admite filtros, y este filtro es una interfaz de interfaz, lo que indica que podemos personalizar la implementación de esta interfaz.
inserte la descripción de la imagen aquí

El código es el siguiente (este método se puede copiar en la clase SMBUtils):

    /**
     * 大于某个时间点的文件
     *
     * @param smbConfig
     * @param time      时间节点
     * @return
     */
    public static List<SmbFile> filesLaterThenTime(SMBConfig smbConfig, long time) {
    
    
        List<SmbFile> res = new ArrayList<>();

        try {
    
    
            UniAddress ua = UniAddress.getByName(smbConfig.getSmbIp());
            NtlmPasswordAuthentication auth = new NtlmPasswordAuthentication(smbConfig.getSmbIp(),
                    smbConfig.getSmbUser(), smbConfig.getSmbPwd());
            SmbSession.logon(ua, auth);
            SmbFile sf = new SmbFile("smb://" + smbConfig.getSmbIp() + "/test" + "/", auth);
            sf.connect();
            SmbFile sffolder = new SmbFile("smb://" + smbConfig.getSmbIp() + "/test" + "/", auth);
			// 设置时间
            SmbLaterThenTimeFileFilter.time.set(time);
            if (sffolder.exists()) {
    
    
            	// 传入自定义过滤器
                SmbFile[] smbFiles = sffolder.listFiles(new SmbLaterThenTimeFileFilter());
                for (SmbFile smbFile : smbFiles) {
    
    
                    res.add(smbFile);
                }
            }
        } catch (Exception e) {
    
    
            e.printStackTrace();
        }
        return res;
    }

Los estudiantes que están familiarizados con el filtro deben saber qué sucede cuando ven el método de aceptación.

import jcifs.smb.SmbException;
import jcifs.smb.SmbFile;
import jcifs.smb.SmbFileFilter;

import java.util.concurrent.atomic.AtomicLong;

/**
 * 过滤器:最新修改时间大于某个时间点
 *
 * @author qkj
 */
public class SmbLaterThenTimeFileFilter implements SmbFileFilter {
    
    
    public static AtomicLong time = new AtomicLong();

    @Override
    public boolean accept(SmbFile smbFile) throws SmbException {
    
    

        // 最后修改时间大于time(也可以替换成自己要的逻辑)
        return smbFile.getLastModified() > time.get();
    }


}

notas sobre smb

Hay diferencias entre smb1.0 y 2.0, y las dependencias también son diferentes.Es necesario confirmar si smb1.0 está habilitado en el servidor de Windows.

Habilite smb1.0 para habilitar o deshabilitar la función de Windows en win10/win11:
inserte la descripción de la imagen aquí

En el servidor de Windows, use el comando para abrir smb1.0 en powerShell:

 Set-SmbServerConfiguration -EnableSMB1Protocol $true

El siguiente es el cuadro de comparación del protocolo predeterminado smb del sistema operativo (para referencia):

inserte la descripción de la imagen aquí

Si el servidor de Windows no tiene una contraseña de cuenta, primero debe configurarla;

Si la función de compartir no está habilitada, debe habilitarse primero
inserte la descripción de la imagen aquí

transmisión java smb2.0/3.0 (modo smbj)

La popularidad del paquete smbj es relativamente alta y no ha anunciado que detendrá el mantenimiento. Sin embargo, el blogger le preguntó al autor de smbj y obtuvo una respuesta de que es imposible filtrar según el momento de creación, modificación, etc. desde el nivel de API. Si no hay tiempo y otras condiciones para filtrar los requisitos (o permitir que el archivo La lista se detecte localmente a través del código para filtrar), puede considerar usar este método.

Las funciones de carga, descarga y lista de 2.0/3.0, el código también se proporciona simplemente:

confiar:

        <!-- smb2.0/3.0 -->
        <dependency>
            <groupId>com.hierynomus</groupId>
            <artifactId>smbj</artifactId>
            <!-- 可以在github中 自行查看当前最新版本-->
            <version>0.11.5</version>
        </dependency>

import com.hierynomus.msdtyp.AccessMask;
import com.hierynomus.msfscc.FileAttributes;
import com.hierynomus.msfscc.fileinformation.FileIdBothDirectoryInformation;
import com.hierynomus.mssmb2.SMB2CreateDisposition;
import com.hierynomus.mssmb2.SMB2CreateOptions;
import com.hierynomus.mssmb2.SMB2ShareAccess;
import com.hierynomus.smbj.SMBClient;
import com.hierynomus.smbj.auth.AuthenticationContext;
import com.hierynomus.smbj.connection.Connection;
import com.hierynomus.smbj.session.Session;
import com.hierynomus.smbj.share.DiskShare;
import com.hierynomus.smbj.share.File;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List;

@Slf4j
public class SMB2Utils {
    
    


    /**
     * SMB下载文件.
     *
     * @param remoteIp  远程IP.
     * @param remoteUrl 远程地址.
     * @param username  远程用户.
     * @param password  远程密码.
     * @param filename  远程文件.
     * @return 共享文件.
     */
    public static byte[] smbDownload(String remoteIp, String remoteUrl, String username, String password,
                                     String filename) {
    
    
        File shareFile = null;
        InputStream shareIs = null;
        ByteArrayOutputStream shareBaos = null;
        SMBClient client = null;
        Session session = null;
        DiskShare diskShare = null;
        Connection connection = null;
        AuthenticationContext authenticationContext = null;

        try {
    
    
            client = new SMBClient();
            connection = client.connect(remoteIp);
            // 创建连接会话.
            authenticationContext = new AuthenticationContext(username, password.toCharArray(), null);
            session = connection.authenticate(authenticationContext);
            // 操作共享文件.
            diskShare = (DiskShare) session.connectShare(remoteUrl);
            // 获取文件流.上传文件.
            shareFile = diskShare.openFile(filename, EnumSet.of(AccessMask.GENERIC_READ),
                    EnumSet.of(FileAttributes.FILE_ATTRIBUTE_NORMAL), SMB2ShareAccess.ALL,
                    SMB2CreateDisposition.FILE_OPEN_IF, EnumSet.noneOf(SMB2CreateOptions.class));
            shareIs = shareFile.getInputStream();
            // 读取文件并下载.
            shareBaos = new ByteArrayOutputStream();
            byte[] buffer = new byte[1024];
            while (shareIs.read(buffer) != -1) {
    
    
                shareBaos.write(buffer);
                buffer = new byte[1024];
            }
            return shareBaos.toByteArray();
        } catch (Exception ex) {
    
    
            log.error(ex.getMessage());
            return null;
        } finally {
    
    
            try {
    
    
                if (null != shareIs) {
    
    
                    shareIs.close();
                }
                if (null != diskShare) {
    
    
                    diskShare.close();
                }
                if (null != session) {
    
    
                    session.close();
                }
                if (null != client) {
    
    
                    client.close();
                }
            } catch (IOException ex) {
    
    
                log.error(ex.getMessage());
                return null;
            }
        }
    }

    /**
     * SMB上传文件.
     *
     * @param remoteIp  远程IP.
     * @param remoteUrl 远程地址.
     * @param username  远程用户.
     * @param password  远程密码.
     * @param filename  远程文件.
     * @param fileBytes 待上传文件.
     * @return 上传结果.
     */
    public static boolean smbUpload(String remoteIp, String remoteUrl, String username, String password,
                                    String filename, byte[] fileBytes) {
    
    
        File shareFile = null;
        OutputStream shareOs = null;
        SMBClient client = null;
        Session session = null;
        DiskShare diskShare = null;
        Connection connection = null;
        AuthenticationContext authenticationContext = null;

        try {
    
    
            client = new SMBClient();
            connection = client.connect(remoteIp);
            // 创建连接会话.
            authenticationContext = new AuthenticationContext(username, password.toCharArray(), null);
            session = connection.authenticate(authenticationContext);
            // 操作共享文件.
            diskShare = (DiskShare) session.connectShare(remoteUrl);
            // 获取文件流.上传文件.
            shareFile = diskShare.openFile(filename, EnumSet.of(AccessMask.GENERIC_WRITE),
                    EnumSet.of(FileAttributes.FILE_ATTRIBUTE_NORMAL), SMB2ShareAccess.ALL,
                    SMB2CreateDisposition.FILE_OPEN_IF, EnumSet.noneOf(SMB2CreateOptions.class));
            shareOs = shareFile.getOutputStream();
            shareOs.write(fileBytes);
            return true;
        } catch (Exception ex) {
    
    
            log.error(ex.getMessage());
            return false;
        } finally {
    
    
            try {
    
    

                if (null != shareOs) {
    
    
                    shareOs.close();
                }
                if (null != shareFile) {
    
    
                    shareFile.close();
                }
                if (null != diskShare) {
    
    
                    diskShare.close();
                }
                if (null != session) {
    
    
                    session.close();
                }
                if (null != client) {
    
    
                    client.close();
                }
            } catch (IOException ex) {
    
    
                log.error(ex.getMessage());
                return false;
            }
        }
    }

    /**
     * SMB删除文件.
     *
     * @param remoteIp  远程IP.
     * @param remoteUrl 远程地址.
     * @param username  远程用户.
     * @param password  远程密码.
     * @param filename  远程文件.
     * @return 删除结果.
     */
    public static boolean smbDelete(String remoteIp, String remoteUrl, String username, String password,
                                    String filename) {
    
    
        SMBClient client = null;
        Session session = null;
        DiskShare diskShare = null;
        Connection connection = null;
        AuthenticationContext authenticationContext = null;

        try {
    
    
            client = new SMBClient();
            connection = client.connect(remoteIp);
            // 创建连接会话.
            authenticationContext = new AuthenticationContext(username, password.toCharArray(), null);
            session = connection.authenticate(authenticationContext);
            // 操作共享文件.
            diskShare = (DiskShare) session.connectShare(remoteUrl);
            // 获取文件流.上传文件.
            diskShare.rm(filename);
            return true;
        } catch (Exception ex) {
    
    
            log.error(ex.getMessage());
            return false;
        } finally {
    
    
            try {
    
    
                if (null != diskShare) {
    
    
                    diskShare.close();
                }
                if (null != session) {
    
    
                    session.close();
                }
                if (null != client) {
    
    
                    client.close();
                }
            } catch (IOException ex) {
    
    
                log.error(ex.getMessage());
                return false;
            }
        }
    }

    /**
     * SMB查看文件列表.
     *
     * @param remoteIp  远程IP.
     * @param remoteUrl 远程地址.
     * @param username  远程用户.
     * @param password  远程密码.
     * @return 结果.
     */
    public static List<FileIdBothDirectoryInformation> smbList(String remoteIp, String remoteUrl, String username, String password) {
    
    
        SMBClient client = null;
        Session session = null;
        DiskShare diskShare = null;
        Connection connection = null;
        AuthenticationContext authenticationContext = null;

        try {
    
    
            client = new SMBClient();
            connection = client.connect(remoteIp);
            // 创建连接会话.
            authenticationContext = new AuthenticationContext(username, password.toCharArray(), null);
            session = connection.authenticate(authenticationContext);
            // 操作共享文件.
            diskShare = (DiskShare) session.connectShare(remoteUrl);

            // 查看文件列表(在已知remoteUrl的情况下 list的path参数为 "/" )
            List<FileIdBothDirectoryInformation> list = diskShare.list("/");
            return list;
        } catch (Exception ex) {
    
    
            log.error(ex.getMessage());
        } finally {
    
    
            try {
    
    
                if (null != diskShare) {
    
    
                    diskShare.close();
                }
                if (null != session) {
    
    
                    session.close();
                }
                if (null != client) {
    
    
                    client.close();
                }
            } catch (IOException ex) {
    
    
                log.error(ex.getMessage());
            }
        }
        return new ArrayList<>();
    }

	// 测试
    public static void main(String[] args) throws Exception {
    
    
        String remoteIp = "192.168.1.1";
        String remoteUrl = "test";
        String username = "xxx";
        String password = "123456";
        String filename = "demo.png";
        byte[] fileBytes = FileUtils.readFileToByteArray(new java.io.File("pom.xml"));
        // 上传文件.
        SMB2Utils.smbUpload(remoteIp, remoteUrl, username, password, filename, fileBytes);
        // 下载文件.
        byte[] downBytes = SMB2Utils.smbDownload(remoteIp, remoteUrl, username, password, filename);
        System.out.println(downBytes.length);
        // 删除文件.
        SMB2Utils.smbDelete(remoteIp, remoteUrl, username, password, filename);
    }
}


transmisión java smb2.0 (modo jcifs-ng)

El método jcifs-ng, similar a jcifs, también se puede usar para el filtrado de tiempo, que es básicamente lo mismo que antes, pero la desventaja es que jcifs-ng ha anunciado que dejará de mantener (smbj también es un proyecto antiguo, y la probabilidad de cambio no es muy grande), y jcifs en línea: hay muy poca información sobre ng, y debe tener cierta capacidad para resolver problemas cuando los encuentre

inserte la descripción de la imagen aquí

1.0-2.0 es compatible de forma predeterminada, si es posible que deba ajustar 3.0 usted mismo.

Dependencia: (debe excluir la dependencia jcifs en smb1 arriba)

        <!-- smb1.0/2.0/部分3.0 方式二 -->
        <dependency>
            <groupId>eu.agno3.jcifs</groupId>
            <artifactId>jcifs-ng</artifactId>
            <version>2.1.9</version>
        </dependency>

código:

  
import com.qiuhuanhen.springroot.domain.model.SMBConfig;
import jcifs.CIFSContext;
import jcifs.context.SingletonContext;
import jcifs.smb.NtlmPasswordAuthenticator;
import jcifs.smb.SmbFile;
import jcifs.smb.SmbFileInputStream;
import lombok.extern.slf4j.Slf4j;

import java.io.*;
import java.util.ArrayList;
import java.util.List;

/**
 * @author qkj
 */
 
@Slf4j
public class SMB23Utils {
    
    
 
    
    public static void main(String[] args) throws Exception {
    
    

        CIFSContext context = withNTLMCredentials(SingletonContext.getInstance());

        SMBConfig smbConfig = new SMBConfig();
        smbConfig.setSmbIp("192.168.1.1");
        smbConfig.setSmbPwd(PASSWORD);
        smbConfig.setSmbUser(USERNAME);
        smbConfig.setSmbPath("/test");
        smbConfig.setSmbFile("1.txt");
        smbConfig.setOs(new FileOutputStream("test1.txt"));
//        smbConfig.setIs(new FileInputStream("1.txt"));
        List<SmbFile> files = filesLaterThenTime(smbConfig,context,1676962027799L);
        retrieveFile(smbConfig, context);
//        storeFile(smbConfig, context);
        context.close();

    }

    /**
     * 列出所有文件
     * @param smbConfig
     * @param context
     * @return
     * @throws Exception
     */
    public static List<SmbFile> files(SMBConfig smbConfig,CIFSContext context) throws Exception {
    
    
        List<SmbFile> res = new ArrayList<>();
        SmbFile sffolder = new SmbFile("smb://" + smbConfig.getSmbIp() + smbConfig.getSmbPath() + "/", context);

        SmbFile[] smbFiles = sffolder.listFiles();
        for (SmbFile smbFile : smbFiles) {
    
    
            res.add(smbFile);
        }
        return res;
    }


    /**
     * 列出某个修改时间点后的文件
     * @param smbConfig
     * @param context
     * @param time
     * @return
     * @throws Exception
     */
    public static List<SmbFile> filesLaterThenTime(SMBConfig smbConfig,CIFSContext context, long time) throws Exception {
    
    
        List<SmbFile> res = new ArrayList<>();
        SmbFile sffolder = new SmbFile("smb://" + smbConfig.getSmbIp() + smbConfig.getSmbPath() + "/", context);

        SmbLaterThenTimeFileFilter.time.set(time);
        SmbFile[] smbFiles = sffolder.listFiles(new SmbLaterThenTimeFileFilter());
        for (SmbFile smbFile : smbFiles) {
    
    
            res.add(smbFile);
        }
        return res;
    }


    /**
     * 往samba上传文件
     *
     * @param smbConfig
     * @return
     */
    public static boolean storeFile(SMBConfig smbConfig, CIFSContext context) {
    
    
        return storeFile(smbConfig.getSmbIp(), context, smbConfig.getSmbPath(), smbConfig.getSmbFile(), smbConfig.getIs());
    }

    /**
     * 从samba下载文件
     *
     * @param smbConfig
     * @return
     */
    public static boolean retrieveFile(SMBConfig smbConfig, CIFSContext context) {
    
    
        return retrieveFile(smbConfig.getSmbIp(), context, smbConfig.getSmbPath(), smbConfig.getSmbFile(), smbConfig.getOs());
    }


    /**
     * 往samba上传文件
     *
     * @param url       服务器IP地址
     * @param storePath 服务器文件存储路径
     * @param fileName  服务器文件存储名称
     * @param is        文件输入流
     * @return true:上传成功
     * <p>
     * false:上传失败
     */
    public static boolean storeFile(String url, CIFSContext context, String storePath, String fileName, InputStream is) {
    
    
        BufferedInputStream bf = null;
        OutputStream os = null;
        boolean result = false;
        SmbFile sf = null;
        try {
    
    
            SmbFile sffolder = new SmbFile("smb://" + url + storePath, context);
            if (!sffolder.exists()) {
    
    
                sffolder.mkdirs();
            }

            sf = new SmbFile("smb://" + url + storePath + "/" + fileName, context);
            sf.connect();

            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();
                if (null != sf)
                    sf.close();
            } catch (IOException e) {
    
    
                log.error(e.getMessage(), e);
            }
        }
        return result;
    }

    /**
     * 从samba下载文件
     *
     * @param url        服务器IP地址
     * @param remotePath 服务器文件存储路径
     * @param fileName   服务器文件存储名称
     * @param os         文件输出流
     * @return true:下载成功
     * <p>
     * false:下载失败
     */
    public static boolean retrieveFile(String url, CIFSContext context, String remotePath, String fileName, OutputStream os) {
    
    
        boolean result = false;
        BufferedInputStream bf = null;
        OutputStream bos = new BufferedOutputStream(os);

        InputStream sf = null;
        SmbFile file = null;
        try {
    
    
            file = new SmbFile("smb://" + url + remotePath + "/" + fileName, context);
            file.connect();

            sf = new SmbFileInputStream(file);

            byte[] bt = new byte[1024];
                int n = sf.read(bt);
                while (n != -1) {
    
    
                    os.write(bt, 0, n);
                    os.flush();
                    n = sf.read(bt);
                }

            result = true;
        } catch (IOException e) {
    
    
            e.printStackTrace();
        } finally {
    
    
            try {
    
    
                if (null != sf)
                    sf.close();
                if (bos != null) {
    
    
                    bos.close();
                }
                if (os != null)
                    os.flush();
                os.close();
                if (bf != null)

                    bf.close();
                if (null!=file)
                file.close();


            } catch (IOException e) {
    
    
                log.error(e.getMessage(), e);
            }
        }


        return result;
    }
    
    public static CIFSContext withNTLMCredentials(CIFSContext ctx) {
    
    
        return ctx.withCredentials(new NtlmPasswordAuthenticator(
                USERNAME, PASSWORD));
    }

}


Código de clase del modelo:

/**
 * 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() {
    
    

    }

}

Este código llama al método de descarga e informará una excepción de nivel de depuración y java.net.SocketException: Socket cerrado después de que se complete la operación. En la actualidad, no se ha encontrado ningún error que afecte el uso. El error de nivel de depuración Fin de archivo El autor dijo en el área del problema que no hay problema, significa que el final Sí, el zócalo cerrado puede ser el mecanismo del zócalo en sí

Supongo que te gusta

Origin blog.csdn.net/qq_36268103/article/details/129145888
Recomendado
Clasificación