java 訪問linux 共享目錄 NFS samba
注:java 訪問NFS 目錄 不好搞,
轉換了一下思路,既然一直無法成功訪問NFS服務。就直接索性操作本地掛載點。針對本地掛載的路徑進行檔案的讀寫操作。這樣就達到了操作NFS共享目錄的效果。
最近需用使用java訪問linux下的共享目錄,實現檔案下載和上傳, 由於linux共享檔案主要採用兩種方式,samba和NFS,samba是基於Microsoft的smb/cifs協議, NFS網路檔案系統(Network File System)則是另一種協議. 對這兩種方式的配置和實現程式碼如下:(配置在Ubuntu下完成)
一,samba
(1)配置:
a ) 建立共享目錄: mkdir /home/pirate/smbshare, chmod 777 smbshare
b) 安裝samba, sudo apt-get install samba, sudo apt-get install smbfs
c) 修改samba配置檔案, sudo gedit /etc/samba/smb.conf, 在檔案最後新增如下行:
[smbshare] #-----共享名字, 客戶端訪問時需使用這個名字
path = /home/pirate/smbshare
available = yes
browsealbe = yes
public = yes
writable = yes
d) 建立共享使用者: sudo useradd aaa
f) 重啟samba, sudo /etc/init.d/samba restart
(2) java訪問
Java程式碼
public void downloadViaShare(final String ip,final String user,final String password,final String <SPAN style="COLOR: #000000">dir</SPAN>)
{
logger.debug("Share(SMB) download!");
String newDir = dir;
String url = "";
SmbFile [] fileList = null;
FileOutputStream fos = null;
SmbFileInputStream smbIs = null;
byte [] buffer = new byte[8192];
int readBytes = 0;
int totalBytes = 0;
if (!dir.endsWith("/")) //directory must end with "/"
newDir = dir+"/";
url = "smb://"+user+":"+password+"@"+ip+"/"+newDir;
long startTime = System.currentTimeMillis();
try {
SmbFile shareDir = new SmbFile(url);
if(shareDir.isDirectory())
{
fileList = shareDir.listFiles();
for(int i=0;i<fileList.length;i++)
{
if(fileList[i].isFile())
{
smbIs = new SmbFileInputStream((SmbFile)fileList[i]);
fos = new FileOutputStream(new File(tempDir+File.separator+fileList[i].getName()));
while((readBytes = smbIs.read(buffer)) > 0 )
{
fos.write(buffer,0,readBytes);
totalBytes += readBytes;
}
smbIs.close();
fos.close();
logger.debug(fileList[i].getName() + " is downloaded!");
try
{
fileList[i].delete();
}catch(SmbAuthException smbae )
{
logger.debug(fileList[i].getName()+" can not be deleted!");
}
}
}
long endTime = System.currentTimeMillis();
long timeTaken = endTime-startTime;
logger.debug(totalBytes +"bytes downloaded in " + timeTaken/1000 + " seconds at "+ (( totalBytes / 1000 ) / Math.max( 1, ( timeTaken / 1000 ))) + "Kb/sec");
}
}catch(MalformedURLException urle)
{
logger.debug("Incorrect URL format!");
}catch (SmbException smbe) {
smbe.printStackTrace();
logger.debug(this.getClass().getName()+"||"+smbe.getMessage());
}catch(IOException ioe)
{
ioe.printStackTrace();
logger.debug(this.getClass().getName()+"||"+ioe.getMessage());
}finally
{
try
{
smbIs.close();
fos.close();
}catch(Exception smbe)
{
logger.debug(this.getClass().getName()+"||"+smbe.getMessage());
}
}
}
二,NFS
(1) 配置
a) 安裝NFS, sudo apt-get install nfs-kernel-server
b) 建立共享目錄: mkdir /home/pirate/nfsshare
c) 編輯配置: sudo gedit /etc/exports ,在最後新增如下行:
/home/pirate/nfsshare *(rw,sync,no_all_squash),含義為:
共享目錄 允許訪問的網路段(讀寫許可權,資料傳送方式,客戶端許可權)
其它Ubuntu nfs常用的引數有:
ro 只讀訪問
rw 讀寫訪問sync 所有資料在請求時寫入共享
async nfs在寫入資料前可以響應請求
secure nfs通過1024以下的安全TCP/IP埠傳送
insecure nfs通過1024以上的埠傳送
wdelay 如果多個使用者要寫入nfs目錄,則歸組寫入(預設)
no_wdelay 如果多個使用者要寫入nfs目錄,則立即寫入,當使用async時,無需此設定。
hide 在nfs共享目錄中不共享其子目錄
no_hide 共享nfs目錄的子目錄
subtree_check 如果共享/usr/bin之類的子目錄時,強制nfs檢查父目錄的許可權(預設)
no_subtree_check 和上面相對,不檢查父目錄許可權
all_squash 共享檔案的UID和GID對映匿名使用者anonymous,適合公用目錄。
no_all_squash 保留共享檔案的UID和GID(預設)
root_squash root使用者的所有請求對映成如anonymous使用者一樣的許可權(預設)
no_root_squas root使用者具有根目錄的完全管理訪問許可權
anonuid=xxx 指定nfs伺服器/etc/passwd檔案中匿名使用者的UID
anongid=xxx 指定nfs伺服器/etc/passwd檔案中匿名使用者的GID
d) 重啟 NFS: sudo service portmap restart , sudo service nfs-kernel-server restart
e) 測試: showmount -e,檢視是否有該目錄的共享
(2) 程式碼
話說這段程式碼雖然很簡單,卻費了我不少力氣。JDK本身是沒有訪問NFS的功能,只能用第三方包了,google後發覺用java訪問NFS的應用很少,竟然沒找到可用的示例,遠不如samba那麼多,而且只有sun的webnfs可用來訪問NFS,在http://yanfs.dev.java.net 上只有一個一個的散裝原始碼, 打包後的jar都沒地方下,連API文件都沒有. 愁煞我也. 找來找去,根據sun的線上文件摸索出了點頭緒.
Java程式碼
public void downloadViaNFS(final String ip,final String user,final String password,final String dir)
{
logger.debug("NFS download begin!");
try {
String url = "nfs://"+ip+"/"+dir;
XFile xf = new XFile(url);
if (xf.exists())
{
logger.debug("URL is OK!");
}else
{
logger.debug("URL is bad!");
return;
}
XFileExtensionAccessor nfsx = (XFileExtensionAccessor)xf.getExtensionAccessor();
if(!nfsx.loginPCNFSD(ip, user, password))
{
logger.debug("login failed!");return;
}
String [] fileList = xf.list();
XFile temp = null;
long startTime = System.currentTimeMillis();
int filesz = 0;
for(String file:fileList)
{
temp = new XFile(url+"/"+file);
XFileInputStream in = new XFileInputStream(temp) ;
XFileOutputStream out = new XFileOutputStream(tempDir+File.separator+file);
int c;
byte[] buf = new byte[8196];
while ((c = in.read(buf)) > 0) {
filesz += c;
out.write(buf, 0, c);
}
logger.debug(file +" is downloaded!");
in.close();
out.close();
if (temp.canWrite())
{
temp.delete();
logger.debug(file + " is deleted!");
}else
{
logger.debug(file + " can not be delted!");
}
}
long endTime = System.currentTimeMillis();
long timeDiff = endTime - startTime;
int rate = (int) ((filesz /1000) / (timeDiff / 1000.0));
logger.debug(filesz + " bytes copied @ " + rate + "Kb/sec");
}catch (IOException e) {
logger.debug(e);
}
}
二,NFS
(1) 配置
a) 安裝NFS, sudo apt-get install nfs-kernel-server
b) 建立共享目錄: mkdir /home/pirate/nfsshare
c) 編輯配置: sudo gedit /etc/exports ,在最後新增如下行:
/home/pirate/nfsshare *(rw,sync,no_all_squash),含義為:
共享目錄 允許訪問的網路段(讀寫許可權,資料傳送方式,客戶端許可權)
其它Ubuntu nfs常用的引數有:
ro 只讀訪問
rw 讀寫訪問sync 所有資料在請求時寫入共享
async nfs在寫入資料前可以響應請求
secure nfs通過1024以下的安全TCP/IP埠傳送
insecure nfs通過1024以上的埠傳送
wdelay 如果多個使用者要寫入nfs目錄,則歸組寫入(預設)
no_wdelay 如果多個使用者要寫入nfs目錄,則立即寫入,當使用async時,無需此設定。
hide 在nfs共享目錄中不共享其子目錄
no_hide 共享nfs目錄的子目錄
subtree_check 如果共享/usr/bin之類的子目錄時,強制nfs檢查父目錄的許可權(預設)
no_subtree_check 和上面相對,不檢查父目錄許可權
all_squash 共享檔案的UID和GID對映匿名使用者anonymous,適合公用目錄。
no_all_squash 保留共享檔案的UID和GID(預設)
root_squash root使用者的所有請求對映成如anonymous使用者一樣的許可權(預設)
no_root_squas root使用者具有根目錄的完全管理訪問許可權
anonuid=xxx 指定nfs伺服器/etc/passwd檔案中匿名使用者的UID
anongid=xxx 指定nfs伺服器/etc/passwd檔案中匿名使用者的GID
d) 重啟 NFS: sudo service portmap restart , sudo service nfs-kernel-server restart
e) 測試: showmount -e,檢視是否有該目錄的共享
(2) 程式碼
話說這段程式碼雖然很簡單,卻費了我不少力氣。JDK本身是沒有訪問NFS的功能,只能用第三方包了,google後發覺用java訪問NFS的應用很少,竟然沒找到可用的示例,遠不如samba那麼多,而且只有sun的webnfs可用來訪問NFS,在http://yanfs.dev.java.net 上只有一個一個的散裝原始碼, 打包後的jar都沒地方下,連API文件都沒有. 愁煞我也. 找來找去,根據sun的線上文件摸索出了點頭緒.
Java程式碼
public void downloadViaNFS(final String ip,final String user,final String password,final String dir)
{
logger.debug("NFS download begin!");
try {
String url = "nfs://"+ip+"/"+dir;
XFile xf = new XFile(url);
if (xf.exists())
{
logger.debug("URL is OK!");
}else
{
logger.debug("URL is bad!");
return;
}
XFileExtensionAccessor nfsx = (XFileExtensionAccessor)xf.getExtensionAccessor();
if(!nfsx.loginPCNFSD(ip, user, password))
{
logger.debug("login failed!");return;
}
String [] fileList = xf.list();
XFile temp = null;
long startTime = System.currentTimeMillis();
int filesz = 0;
for(String file:fileList)
{
temp = new XFile(url+"/"+file);
XFileInputStream in = new XFileInputStream(temp) ;
XFileOutputStream out = new XFileOutputStream(tempDir+File.separator+file);
int c;
byte[] buf = new byte[8196];
while ((c = in.read(buf)) > 0) {
filesz += c;
out.write(buf, 0, c);
}
logger.debug(file +" is downloaded!");
in.close();
out.close();
if (temp.canWrite())
{
temp.delete();
logger.debug(file + " is deleted!");
}else
{
logger.debug(file + " can not be delted!");
}
}
long endTime = System.currentTimeMillis();
long timeDiff = endTime - startTime;
int rate = (int) ((filesz /1000) / (timeDiff / 1000.0));
logger.debug(filesz + " bytes copied @ " + rate + "Kb/sec");
}catch (IOException e) {
logger.debug(e);
}
}