1. 程式人生 > >java 訪問linux 共享目錄 NFS samba

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);

  }

  }