Java中SMB的相关应用

Java中SMB的相关应用

SMB简介

SMB(全称是Server Message Block)是一个协议名,它能被用于Web毗邻和客户端与服务器之间的信息沟通。SMB协议作为一种局域网文件共享传输协议,常被用来作为共享文件平安传输研究的平台。

Windows操作系统都包罗了客户机和服务器SMB协议支持。Microsoft为 Internet提供了SMB的开源版本,即通用Internet文件系统CIFS。与现有Internet应用程序如文件传输协议FTP相比, CIFS灵活性更大。对于UNIX系统,可使用一种称为Samba的共享软件。

引入SMB依赖

pom.xml中引入SMB服务相关的依赖:

<!-- 引用SmbFile类的jar包  -->
<dependency>
       <groupId>jcifs</groupId>
       <artifactId>jcifs</artifactId>
       <version>1.3.17</version>
</dependency>

路径花样

在Java中通过SMB接见远程共享目录的请求花样有如下三种情形:(以test共享文件夹下的test.txt文件示例)

  • 若是是无需密码的共享,花样类似:smb://ip/sharefolder/filename(例如:smb://192.168.1.106/test/test.txt
  • 若是需要用户名和密码,花样类似:smb://username:password@ip/sharefolder/filename(例如:smb://admin:damin@192.168.1.106/test/test.txt
  • 若是需要用户名密码和域名,花样类似:smb:host;username:password@ip/sharefolder/filename(例如:smb://orcl;admin:admin@192.168.1.106/test/test.txt

上传下载

具备了以上环节的准备,就可以在项目中实现SMB相关的应用;下面是一个简朴的从共享文件夹目录中将文件下载到指定文件夹的方式。

redis 主从同步&哨兵模式&codis

package com.example.smb;
import jcifs.smb.SmbFile;
import jcifs.smb.SmbFileInputStream;
import org.springframework.util.FileCopyUtils;
import java.io.*;
/**
 * @author: Create By 成猿手册
 * @description: Java中SMB的上传和下载
 * @date: 2020/03/22
 */
public class Demo {

    private static final String SMB_SHARE_FOLDER = "smb://admin:admin@192.168.1.106/Test/";
    private static final String SHARE_FOLDER_PATH = "2020-03-21\\result";
    private static final String FILE_NAME = "myresult.txt";
    private static final String LOCAL_DIR = "D:\\LocalTest";

    public static void main(String[] args) {
        downloadSmbFile(SMB_SHARE_FOLDER, SHARE_FOLDER_PATH, FILE_NAME, LOCAL_DIR);
    }

    /**
     * 从SMB共享文件夹下载文件到内陆
     * @param smburl      smb请求的url
     * @param shareFolder 共享文件夹中目的文件存放的完整路径
     * @param fileName    要下载/上传的完整文件名
     * @param localDir    要上传/下载的完整文件夹路径
     */
    public static void downloadSmbFile(String smburl, String shareFolder, String fileName, String localDir) {
        InputStream in = null;
        OutputStream out = null;
        try {
            SmbFile smbfile = 
                new SmbFile(smburl + shareFolder + File.separator + fileName);
            File localFile = new File(localDir + File.separator + fileName);
            //文件上传到SMB共享文件目录与该写法类似;即使用SmbFileOutputStream(smbfile);
            in = new BufferedInputStream(new SmbFileInputStream(smbfile));
            out = new BufferedOutputStream(new FileOutputStream(localFile));
            FileCopyUtils.copy(in, out);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            closeStreanm(in, out);
        }
    }
    //关闭文件流
    private static void closeStreanm(InputStream in, OutputStream out) {
        try {
            if (in != null) {
                in.close();
            }
            if (out != null) {
                out.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

不难发现,对SMB共享文件的操作放在Java中实在就是转换为操作SmbFile这个工具,一旦乐成构建(正当的url ,准确的canon等需要属性)该工具,许多问题也就变得简朴起来。

例如,自己事情中有一个营业需求是要检测SMB共享目录中的某个文件是否存在,代码示例如下:

    /**
     * 检测SMB共享文件夹中的文件是否存在
     * @param smburl      smb请求的url
     * @param shareFolder 共享文件夹中目的文件存放的完整路径
     * @param fileName    要检测文件的完整文件名
     */
public static boolean checkSmbFile(String smburl, String shareFolder, String fileName) {
    boolean result = false;
    try {
        SmbFile smbfile = 
            new SmbFile(smburl + shareFolder + File.separator + fileName);
        result = smbfile.exists();
    } catch (Exception e) {
        e.printStackTrace();
    }
    return result;
}

登录验证

在这里使用登录验证主要是为解决账号密码中含有特殊字符的情形(好比转义字符,链接里的特定字符),存在特殊字符的账号密码再使用上面的路径去请求SMB服务往往会报出下列异常:

Connected to the target VM, address: '127.0.0.1:54593', transport: 'socket'
jcifs.smb.SmbAuthException: Logon failure: unknown user name or bad password.

这时为了构建正当的SmbFile工具,我们就换一种思绪:先举行登录验证,再去实验构建该工具:

package com.example.smb;
import jcifs.smb.NtlmPasswordAuthentication;
import jcifs.smb.SmbFile;
import java.net.MalformedURLException;
/**
 * @author: Create By 成猿手册
 * @description: smb账号密码中含有特殊字符的处置方式
 * @date: 2020/3/22
 */
public class SmbFileHelper {
    public static SmbFile newSmbFile(SmbFileInfo smbFileInfo) throws MalformedURLException {
        NtlmPasswordAuthentication auth =
                new NtlmPasswordAuthentication(smbFileInfo.getIp(), smbFileInfo.getUsername(), smbFileInfo.getPassword());
        String smburl = String.format("smb://%s/%s", smbFileInfo.getIp(), smbFileInfo.getFilepath());
        return new SmbFile(smburl, auth);
    }
}

SmbFileInfo类的写法:

package com.example.smb;
/**
 * @author: Create By 成猿手册
 * @description: SmbFileInfo实体类
 * @date: 2020/3/22
 */
public class SmbFileInfo {
    private String ip;
    private String username;
    private String password;
    private String filepath;
    //这里省略了get()和set()方式
}

原创文章,作者:870t新闻网,如若转载,请注明出处:https://www.870t.com/archives/2208.html