引入:
在我们昨天架设好了Samba服务器上并且创建了一个 Samba 账户后,我们就迫不及待的想用JAVA去操作Samba服务器了,我们找到了一个框架叫 jcifs,可以高效的完成我们工作。
实践:
对samba服务器上的操作无外乎2种:一种是从Samba服务器上下载某文件到本地目录,一种是上传本地文件到Samba服务器上指定目录,为此我们写了一个工具类,来完成这两件事情。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
|
package
com.charles.study;
import
java.io.BufferedInputStream;
import
java.io.BufferedOutputStream;
import
java.io.File;
import
java.io.FileInputStream;
import
java.io.FileOutputStream;
import
java.io.IOException;
import
java.io.InputStream;
import
java.io.OutputStream;
import
jcifs.smb.SmbFile;
import
jcifs.smb.SmbFileInputStream;
import
jcifs.smb.SmbFileOutputStream;
/**
* 这个工具类提供了从Samba服务器上下载文件到本地目录,以及上传本地文件到Samba服务器指定目录的方法
* @author charles.wang
*
*/
public
class
SambaFileAccessUtil {
private
SambaFileAccessUtil() {}
/**
* 从samba服务器上下载指定的文件到本地目录
* @param remoteFileURL Samba服务器远程文件的路径
* @param localDir 本地目录的路径
*/
public
static
void
downloadFileFromSamba(String remoteFileURL, String localDir){
//入参检查
if
( (remoteFileURL==
null
) || (
""
.equals(remoteFileURL.trim()))){
System.out.println(
"Samba服务器远程文件路径不可以为空"
);
return
;
}
//入参检查
if
( (localDir==
null
) || (
""
.equals(localDir.trim()))){
System.out.println(
"本地目录路径不可以为空"
);
return
;
}
InputStream in =
null
;
OutputStream out =
null
;
try
{
//创建一个smbFile对象对应远程服务器上的SmbFile
SmbFile remoteSmbFile =
new
SmbFile(remoteFileURL);
//获取远程文件的文件名,这个的目的是为了在本地的目录下创建一个同名文件
String remoteSmbFileName = remoteSmbFile.getName();
//本地文件由本地目录,路径分隔符,文件名拼接而成
File localFile =
new
File(localDir+File.separator+remoteSmbFileName);
//打开文件输入流,指向远程的smb服务器上的文件,特别注意,这里流包装器包装了SmbFileInputStream
in=
new
BufferedInputStream(
new
SmbFileInputStream(remoteSmbFile));
//打开文件输出流,指向新创建的本地文件,作为最终复制到的目的地
out =
new
BufferedOutputStream(
new
FileOutputStream(localFile));
//缓冲内存
byte
[] buffer =
new
byte
[
1024
];
while
(in.read(buffer) != -
1
){
out.write(buffer);
buffer =
new
byte
[
1024
];
}
}
catch
(Exception e){
e.printStackTrace();
}
finally
{
try
{
out.close();
in.close();
}
catch
(IOException e) {
e.printStackTrace();
}
}
}
/**
* 上传本地文件到Samba服务器指定目录
* @param remoteDirURL Samba服务器远程目录的路径
* @param localFilePath 本地文件路径
*/
public
static
void
uploadFileToSamba(String remoteDirURL,String localFilePath){
//入参检查
if
( (remoteDirURL==
null
) || (
""
.equals(remoteDirURL.trim()))){
System.out.println(
"Samba服务器远程目录路径不可以为空"
);
return
;
}
//入参检查
if
( (localFilePath==
null
) || (
""
.equals(localFilePath.trim()))){
System.out.println(
"本地文件路径不可以为空"
);
return
;
}
InputStream in =
null
;
OutputStream out =
null
;
try
{
//创建一个本地文件对象
File localFile =
new
File(localFilePath);
//获取本地文件的文件名,这个名字用于在远程的Samba服务器上指定目录创建同名文件
String localFileName = localFile.getName();
//创建远程服务器上Samba文件对象
SmbFile remoteSmbFile =
new
SmbFile(remoteDirURL+File.separator+localFileName);
//打开一个文件输入流执行本地文件,要从它读取内容
in =
new
BufferedInputStream(
new
FileInputStream(localFile));
//打开一个远程Samba文件输出流,作为复制到的目的地
out =
new
BufferedOutputStream(
new
SmbFileOutputStream(remoteSmbFile));
//缓冲内存
byte
[] buffer =
new
byte
[
1024
];
while
(in.read(buffer) != -
1
) {
out.write(buffer);
buffer =
new
byte
[
1024
];
}
}
catch
(Exception e) {
e.printStackTrace();
}
finally
{
try
{
out.close();
in.close();
}
catch
(IOException e) {
e.printStackTrace();
}
}
}
}
|
为了验证我们的正确性,我们写了某测试类。
测试1: 从Samba服务器上下载某文件到本地。
我们先做好准备工作,因为Samba服务器上多半是存图片等资源文件的,所以我们也以图片为例。
我们在Samba服务器的/home/samba/目录下新建一个子目录叫demo1,并且放上去一个图片叫testFile1.jpg,这个文件作为我们要从Samba服务器上下载的目标文件:
然后我们在本地的D:\Framework Study\Samba\DemoTest下创建一个子目录叫demo1,这里作为最终的要下载到本地的目录:
我们运行如下DEMO代码:
1
2
3
4
5
|
//Demo1: 演示从Samba服务器上下载指定的文件到本地
System.out.println(
"Demo1: Downloading File from Samba Server to Local"
);
String demo1RemoteSambaFileURL=
"smb://samba:samba_password@192.168.71.43/samba/demo1/testFile1.jpg"
;
String demo1LocalDir =
"D:\\Framework Study\\Samba\\DemoTest\\demo1"
;
SambaFileAccessUtil.downloadFileFromSamba(demo1RemoteSambaFileURL, demo1LocalDir);
|
这里注意,我们的Samba服务器上的远程文件URL必须是smb协议开头,因为我们对于samba目录加了访问控制,所以要<username>:<password>@<ip>/<path>的形式,否则,可以吧<username>:<password>去掉。
运行完之后,果然该图片文件被复制到了本地:
测试2:上传本地文件到Samba服务器指定目录
我们同样做好准备工作,我们在本地的D:\Framework Study\Samba\DemoTest下创建一个子目录叫demo2,并且放置一个图片叫testFile2.jpg,这个文件作为要上传到Samba服务器的原始文件:
然后我们在Samba服务器的/home/samba/目录下新建一个子目录叫demo2,这个目录作为我们要上传到的Samba服务器的目录:
我们运行如下的DEMO代码:
1
2
3
4
5
|
//Demo2: 演示上传文件到Samba服务器指定目录
System.out.println(
"Demo2:Uploading File from Local to Samba Server"
);
String demo2RemoteSambaDirURL=
"smb://samba:samba_password@192.168.71.43/samba/demo2"
;
String demo2LocalFile=
"D:\\Framework Study\\Samba\\DemoTest\\demo2\\testFile2.jpg"
;
SambaFileAccessUtil.uploadFileToSamba(demo2RemoteSambaDirURL, demo2LocalFile);
|
运行完之后,果然这个testFile2.jpg被上传到了Samba服务器:
总结:
其实用samba来作为windows和unix类系统之间文件共享的桥梁还是挺方便的,类似unix之间的scp(jsch框架可以完成这件事情) ,其实方法都一样。这里有2个注意点:
(1)在写samba url时候,如果目标目录是一个需要特定账号密码才能访问的,那么这个url pattern为
smb://<samba username>:<samba userpassword>@<samba server ip>/<subpath>,如果某个目录是public的(设了guest ok的),那么url pattern是 smb://<samba server ip>/<subpath>
(2) 这里只提供了上传下载单文件的方法,如果要批上传下载或者操作目录,请递归或者循环调用上面工具类的方法。