三默网为您带来有关“SMB 协议操作共享盘”的文章内容,供您阅读参考。

SMB 协议操作共享盘

2023-01-21 19:35:10

1、添加依赖

          <dependency>
            <groupId>jcifs</groupId>
            <artifactId>jcifs</artifactId>
            <version>1.3.17</version>
          </dependency>

2、示例工具类

import jcifs.smb.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.springframework.util.CollectionUtils;

import java.io.*;
import java.net.MalformedURLException;
import java.util.*;

/**
 * 共享盘操作工具类
 */
@Slf4j
public class SmbFileUtils {
    /**
     * 递归获取共享盘某个目录下的文件列表
     *
     * @param container
     * @param dir
     * @return
     * @throws SmbException
     */
    public static void listSmbFilesByPrefixAndSuffix(List<SmbFile> container, SmbFile dir,
                                                     String filePrefix, String fileSuffix) throws SmbException {
        SmbFile[] files = dir.listFiles();
        Arrays.stream(files).forEach(smbFile -> {
            try {
                if (smbFile.isDirectory()) {
                    listSmbFilesByPrefixAndSuffix(container, smbFile, filePrefix, fileSuffix);
                } else {
                    String fileName = smbFile.getName();
                    if (fileName.contains(filePrefix) && fileName.endsWith(fileSuffix.toLowerCase())) {
                        container.add(smbFile);
                    }
                }
            } catch (SmbException e) {
                e.printStackTrace();
            }
        });
    }

    /**
     * 根据规则递归获取共享盘某个目录下的文件
     *
     * @param sharedPath
     * @return
     * @throws SmbException
     */
    public static List<String> listFileBySuffixAndLastSyncTime(String username, String password,
                                                               String sharedPath, String fileSuffix,
                                                               String lastSyncTime) throws Exception {
        sharedPath = tailWrap(sharedPath);
        NtlmPasswordAuthentication auth = new NtlmPasswordAuthentication("", username, password);
        SmbFile dir = new SmbFile(sharedPath, auth);
        dir.connect();
        if (!dir.exists() || !dir.isDirectory()) {
            throw new Exception(sharedPath + "路径不存在!");
        }
        List<SmbFile> files = new ArrayList<>();
        //从指定目录开始获取目录下所有文件
        recursiveDir(files, dir);
        List<String> result = new ArrayList<>();
        try {
            if (!CollectionUtils.isEmpty(files)) {
                String finalSharedPath = sharedPath;
                files.forEach(file -> {
                    String name = file.getName();
                    boolean condition = false;
                    try {
                        condition = name.endsWith(fileSuffix.toLowerCase()) && CalendarUtil.lastModifiedBetween(file.lastModified(), lastSyncTime, CalendarUtil.getCurrentYMDHMS());
                    } catch (SmbException e) {
                        e.printStackTrace();
                    }
                    if (condition) {
                        //获取相对于指定路径的文件名
                        String fileNameWithRelativePath = file.getPath().substring(finalSharedPath.length() - 1);
                        result.add(fileNameWithRelativePath);
                    }
                });
            }
        } catch (Exception e) {
            e.printStackTrace();
            return Collections.emptyList();
        }
        log.info("满足配置要求的文件数量为:->{}", result.size());
        return result;
    }



    /**
     * 根据规则遍递归遍历文件夹中的文件
     *
     * @param sharedPath
     * @param prefix       文件前缀
     * @param suffix
     * @param lastSyncTime
     * @return
     * @throws Exception
     */
    public static List<String> listFileByPrefixAndSuffixAndLastSyncTime(String username, String password,
                                                                        String sharedPath, String prefix,
                                                                        String suffix, String lastSyncTime) throws Exception {
        sharedPath = tailWrap(sharedPath);
        String currentTime = CalendarUtil.getCurrentYMDHMS();
        NtlmPasswordAuthentication auth = new NtlmPasswordAuthentication("", username, password);
        SmbFile dir = new SmbFile(sharedPath, auth);
        dir.connect();
        if (!dir.exists() || !dir.isDirectory()) {
            throw new Exception(sharedPath + "路径不存在!");
        }
        List<SmbFile> files = new ArrayList<>();
        recursiveDir(files, dir);
        List<String> result = new ArrayList<>();
        if (!CollectionUtils.isEmpty(files)) {
            String finalSharedPath = sharedPath;
            files.forEach(file -> {
                String name = file.getName();
                boolean condition = false;
                try {
                    condition = name.contains(prefix) && name.endsWith(suffix.toLowerCase()) && CalendarUtil.lastModifiedBetween(file.lastModified(), lastSyncTime, currentTime);
                } catch (SmbException e) {
                    e.printStackTrace();
                }
                if (condition) {
                    String fileNameWithRelativePath = file.getPath().substring(finalSharedPath.length() - 1);
                    result.add(fileNameWithRelativePath);
                }
            });
        }
        log.info("满足配置要求的文件数量为:->{}", result.size());
        return result;
    }

    /**
     * 根据规则遍递归遍历文件夹中的文件
     *
     * @param sharedPath
     * @param prefix         文件前缀
     * @param suffix
     * @param fileTimeFormat
     * @return
     * @throws Exception
     */
    public static List<String> listFileByPrefixAndSuffixAndTime(String username, String password,
                                                                String sharedPath, String prefix,
                                                                String suffix, String fileTimeFormat) throws Exception {
        sharedPath = tailWrap(sharedPath);
        NtlmPasswordAuthentication auth = new NtlmPasswordAuthentication("", username, password);
        SmbFile dir = new SmbFile(sharedPath, auth);
        dir.connect();
        if (!dir.exists() || !dir.isDirectory()) {
            throw new Exception(sharedPath + "路径不存在!");
        }
        List<SmbFile> files = new ArrayList<>();
        recursiveDir(files, dir);
        List<String> result = new ArrayList<>();
        if (!CollectionUtils.isEmpty(files)) {
            String finalSharedPath = sharedPath;
            files.forEach(file -> {
                String name = file.getName();
                boolean condition = name.contains(prefix) && name.endsWith(suffix.toLowerCase()) && name.contains(fileTimeFormat);
                if (condition) {
                    String fileNameWithRelativePath = file.getPath().substring(finalSharedPath.length());
                    result.add(fileNameWithRelativePath);
                }
            });
        }
        log.info("满足配置要求的文件数量为:->{}", result.size());
        return result;
    }

    /**
     * 递归获取目录下的文件列表
     *
     * @param list
     * @param dir
     * @return
     */
    private static void recursiveDir(List<SmbFile> list, SmbFile dir) throws SmbException {
        SmbFile[] smbFiles = dir.listFiles();
        log.info("正在遍历的共享(SMB)文件夹为:->{}", dir.getPath());
        Arrays.stream(smbFiles).forEach(smbFile -> {
                    try {
                        if (smbFile.isDirectory()) {
                            recursiveDir(list, smbFile);
                        } else if (smbFile.isFile()) {
                            list.add(smbFile);
                        }
                    } catch (SmbException e) {
                        e.printStackTrace();
                    }
                }
        );
    }

    /**
     * 上传文件到共享盘
     *
     * @param aimDir
     * @param fileName
     * @param inputStream
     * @return
     */
    public static boolean upload(
            String username, String password,
            String aimDir, String fileName,
            InputStream inputStream) {
        try {
            //检查文件名字是否携带目录层级
            File file = new File(fileName);
            String parent = file.getParent();
            if (Objects.isNull(parent)) {
                parent = "/";
            }
            if (parent.contains("\\")) {
                parent = parent.replace("\\\\", "/");
            }
            if (!aimDir.endsWith("/") && !parent.startsWith("/")) {
                aimDir = aimDir + "/";
            }
            String desDir = aimDir + parent;
            if (!desDir.endsWith("/")) {
                desDir += "/";
            }
            if (!createDir(username, password, desDir)) {
                throw new RuntimeException("文件夹创建失败!->" + desDir);
            }
            NtlmPasswordAuthentication auth = new NtlmPasswordAuthentication("", username, password);
            SmbFile aimFile = new SmbFile(desDir + file.getName(), auth);
            aimFile.connect();
            if (aimFile.isFile() && aimFile.exists()) {
                aimFile.delete();
            }
            aimFile.createNewFile();
            if (inputStream == null) {
                throw new Exception(fileName + "的文件流为null!");
            }
            byte[] buffer = new byte[inputStream.available()];
            inputStream.read(buffer);
            OutputStream outStream = new SmbFileOutputStream(aimFile);
            outStream.write(buffer);
            inputStream.close();
            outStream.close();
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

    public static boolean createDir(String username, String password, String path) {
        try {
            NtlmPasswordAuthentication auth = new NtlmPasswordAuthentication("", username, password);
            SmbFile smbFileDir = new SmbFile(path, auth);
            smbFileDir.connect();
            boolean flag = smbFileDir.exists();
            if (flag) {
                return true;
            }
            smbFileDir.mkdirs();
            log.info("目录:{},创建成功!", path);
            return true;
        } catch (MalformedURLException e) {
            e.printStackTrace();
            return false;
        } catch (SmbException e) {
            e.printStackTrace();
            return false;
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 获取文件流
     *
     * @param smbDir
     * @return
     * @throws IOException
     */
    public static InputStream getFileInputStream(String username, String password, String smbDir, String fileName) {
        SmbFileInputStream fis = null;
        byte[] bytes = null;
        try {
            NtlmPasswordAuthentication auth = new NtlmPasswordAuthentication("", username, password);
            if (!smbDir.endsWith("/") && !fileName.startsWith("/")) {
                SmbFile smbFile = new SmbFile(smbDir + "/" + fileName, auth);
                fis = new SmbFileInputStream(smbFile);
                bytes = IOUtils.toByteArray(fis);
                fis.close();
                InputStream inputStream = new ByteArrayInputStream(bytes);
                return inputStream;
            } else {
                SmbFile smbFile = new SmbFile(smbDir + fileName, auth);
                fis = new SmbFileInputStream(smbFile);
                bytes = IOUtils.toByteArray(fis);
                fis.close();
                InputStream inputStream = new ByteArrayInputStream(bytes);
                return inputStream;
            }
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 删除文件
     *
     * @param smbDir
     * @return
     * @throws IOException
     */
    public static boolean deleteFile(String username, String password, String smbDir, String fileName) throws IOException {
        try {
            NtlmPasswordAuthentication auth = new NtlmPasswordAuthentication("", username, password);
            if (!smbDir.endsWith("/") && !fileName.startsWith("/")) {
                SmbFile smbFile = new SmbFile(smbDir + "/" + fileName, auth);
                if (smbFile.isFile() && smbFile.exists()) {
                    smbFile.delete();
                }
            } else {
                SmbFile smbFile = new SmbFile(smbDir + fileName, auth);
                if (smbFile.isFile() && smbFile.exists()) {
                    smbFile.delete();
                }
            }
            return true;
        } catch (MalformedURLException e) {
            e.printStackTrace();
            return false;
        } catch (SmbException e) {
            e.printStackTrace();
            return false;
        }
    }

    private static String tailWrap(String tail) {
        if (!tail.endsWith("/")) {
            tail += "/";
        }
        return tail;
    }
}

注意事项:
①路径必须是smb://开头且以“/”结束 如 smb://127.0.0.1/D$/shareDisk/
②如果操作windows上的某个共享磁盘,若该磁盘没有指定共享名,须使用盘符加$代替,如操作D盘,路径里面不能写为D:\\ 应为"D$" 如 smb://127.0.0.1/D$/shareDisk/