Java中SMB的相关应用
发布日期:2022-02-17 04:52:23 浏览次数:13 分类:技术文章

本文共 4684 字,大约阅读时间需要 15 分钟。

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服务相关的依赖:

jcifs
jcifs
1.3.17

路径格式

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

转载地址:https://blog.csdn.net/qq_41429510/article/details/105038274 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:Windows搭建SMB服务
下一篇:Windows生成项目目录结构

发表评论

最新留言

很好
[***.229.124.182]2024年03月18日 12时13分05秒

关于作者

    喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!

推荐文章

php+mysql记事本_一个简单记事本php操作mysql辅助类创建 2019-04-21
300小时成为java程序员_直击面试现场: Java程序员3轮6小时面试, 成功拿到阿里offer!... 2019-04-21
中国网建java发送短信_短信验证登陆-中国网建提供的SMS短信平台 2019-04-21
隔行变色java代码_jquery入门—选择器实现隔行变色实例代码 2019-04-21
角标越界 Java_【新人求助】利用占位符操作数据库是总是提示数组角标越界是怎么回事 - Java论坛 - 51CTO技术论坛_中国领先的IT技术社区... 2019-04-21
java类中声明log对象_用于Android环境,java环境的log打印,可打印任何类型数据 2019-04-21
db2与mysql编目_DB2编目、联邦数据库 - Goopand's OS Space - OSCHINA - 中文开源技术交流社区... 2019-04-21
atomikosdatasourcebean mysql_SpringBoot2整合JTA组件实现多数据源事务管理 2019-04-21
webpack 入口文件 php,如何实现webpack多入口文件打包配置 2019-04-21
php tire树,Immutable.js源码之List 类型的详细解析(附示例) 2019-04-21
matlab转差频率控制,转差频率控制的异步电机调速系统的研究 2019-04-21
oracle错误1327,Oracle中的PGA监控报警分析(r11笔记第97天) 2019-04-21
php函数内的循环,PHP 循环列出目录内容的函数代码 2019-04-21
oracle树状排序,Oracle树状结构查询 2019-04-21
深度linux内核升级,深度操作系统 2020.11.11 更新发布:内核升级 2019-04-21
sql 拆解函数_SQL入门50题详解(含知识点讲解及代码运行步骤拆解) 2019-04-21
java和python交互 jni_Python基于pyjnius库实现访问java类 2019-04-21
macbook pro 卸载mysql_MacBook Pro全新重装OS X Yosemite 2019-04-21
已达到计算机的连接数最大值无法再同此远程计算机连接_电脑远程访问已达到计算机的连接数最大值怎么办?解决方法很简单... 2019-04-21
mysql表名长度_JavaWeb之MySQL(一) 2019-04-21