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相关的应用;下面是一个简单的从共享文件夹目录中将文件下载到指定文件夹的方法。

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()方法
}

原文 

http://www.cnblogs.com/WangJpBlog/p/12549216.html

本站部分文章源于互联网,本着传播知识、有益学习和研究的目的进行的转载,为网友免费提供。如有著作权人或出版方提出异议,本站将立即删除。如果您对文章转载有任何疑问请告之我们,以便我们及时纠正。

PS:推荐一个微信公众号: askHarries 或者qq群:474807195,里面会分享一些资深架构师录制的视频录像:有Spring,MyBatis,Netty源码分析,高并发、高性能、分布式、微服务架构的原理,JVM性能优化这些成为架构师必备的知识体系。还能领取免费的学习资源,目前受益良多

转载请注明原文出处:Harries Blog™ » Java中SMB的相关应用

赞 (0)
分享到:更多 ()

评论 0

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址