最近需用使用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访问

   

    访问Samba共享依赖于一个第三方包:jcifs-1.3.15.jar, 下载地址http://jcifs.samba.org/

Java代码   
   

 
   
 
1. public void downloadViaShare(final String ip,final String user,final String password,final String <span style="color: #000000;">dir</span>)  
2.     {  
3. "Share(SMB) download!");  
4.           
5.         String newDir = dir;          
6. "";    
7. null;  
8. null;  
9. null;  
10. byte [] buffer = new byte[8192];  
11. int readBytes = 0;  
12. int totalBytes = 0;  
13.               
14. if (!dir.endsWith("/"))  //directory must end with "/"      
15. "/";    
16. "smb://"+user+":"+password+"@"+ip+"/"+newDir;  
17.           
18. long
19. try
20. new
21. if(shareDir.isDirectory())  
22.             {  
23.                 fileList = shareDir.listFiles();    
24. for(int i=0;i<fileList.length;i++)    
25.                 {  
26. if(fileList[i].isFile())  
27.                     {  
28. new
29. new FileOutputStream(new
30. while((readBytes = smbIs.read(buffer)) > 0
31.                         {  
32. 0,readBytes);  
33.                             totalBytes += readBytes;  
34.                         }  
35.                         smbIs.close();  
36.                         fos.close();  
37. " is downloaded!");  
38. try
39.                         {  
40.                             fileList[i].delete();    
41. catch(SmbAuthException smbae )  
42.                         {  
43. " can not be deleted!");  
44.                         }  
45.                     }  
46.                 }  
47. long
48. long
49. "bytes downloaded in " + timeTaken/1000 + " seconds at "+ (( totalBytes / 1000 ) / Math.max( 1, ( timeTaken / 1000 ))) + "Kb/sec");  
50.             }  
51. catch(MalformedURLException urle)  
52.         {  
53. "Incorrect URL format!");  
54. catch
55.             smbe.printStackTrace();  
56. this.getClass().getName()+"||"+smbe.getMessage());  
57. catch(IOException ioe)  
58.         {  
59.             ioe.printStackTrace();  
60. this.getClass().getName()+"||"+ioe.getMessage());  
61. finally
62.         {  
63. try
64.             {  
65.                 smbIs.close();  
66.                 fos.close();  
67. catch(Exception smbe)  
68.             {  
69. this.getClass().getName()+"||"+smbe.getMessage());  
70.             }  
71.         }  
72.           
73.     }

二,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代码   
   

 
   
 
1. public void downloadViaNFS(final String ip,final String user,final String password,final
2.     {  
3. "NFS download begin!");  
4. try
5.               
6. "nfs://"+ip+"/"+dir;               
7. new
8. if
9.             {  
10. "URL is OK!");  
11. else
12.             {  
13. "URL is bad!");  
14. return;  
15.             }  
16.                           
17.             XFileExtensionAccessor nfsx = (XFileExtensionAccessor)xf.getExtensionAccessor();  
18. if(!nfsx.loginPCNFSD(ip, user, password))  
19.             {  
20. "login failed!");return;  
21.             }  
22.               
23.             String [] fileList = xf.list();  
24. null;  
25. long
26. int filesz = 0;  
27. for(String file:fileList)  
28.             {  
29. new XFile(url+"/"+file);  
30. new
31. new
32.   
33. int
34. byte[] buf = new byte[8196];             
35.                   
36.                           
37.   
38. while ((c = in.read(buf)) > 0) {                  
39.                      filesz += c;                  
40. 0, c);                       
41.                 }              
42.   
43. " is downloaded!");         
44.                 in.close();              
45.                 out.close();          
46. if
47.                 {  
48.                     temp.delete();  
49. " is deleted!");  
50. else
51.                 {  
52. " can not be delted!");  
53.                 }  
54.             }  
55. long
56. long
57. int rate = (int) ((filesz /1000) / (timeDiff / 1000.0));  
58. " bytes copied @ " + rate + "Kb/sec");  
59.              
60. catch
61.                 logger.debug(e);          
62.             }  
63.           
64.     } 
• 首先在Linux上创建一个共享文件夹
 mkdir /home/user/share
• 用root用户启动samba服务
 service smb start
• 修改smb.conf文件
 sudo gedit /etc/samba/smb.conf 或者 vi /etc/samba/smb.conf
 [share]
 path = /home/user/share
 ...
 writable = yes
• 创建共享用户并设置密码
 sudo useradd smbusr
 sudo smbpasswd -a smbusr
 使用命令 sudo smbpasswd -x 删除用户
• 重启samba服务
 service smb restart
• 测试
 在windows中输入//192.168.0.94,并输入用户名密码smbusr/***,看能不能访问到共享文件夹。如果可以的话拷贝一份本地txt文件到此目录,并在linux中查看此文件是否存在,如果用vi能够打开文件文件并正常查看其内容,congruatulations!
• 用jcifs测试文件操作
 去下 载适当版本的jcifs,将jcifs-1.3.14.jar加入到项目工程中。写个测试类共享文件操作:
 
 
  
 
     [java]  
     view plain 
     copy 
     
 
     
 
   
1. public static void main(String[] args) {  
2.           
3. null;  
4. null;  
5. try {  
6. new FileInputStream(new File("c:/source.txt"));  
7. new SmbFileOutputStream(new SmbFile("smb://smbusr:smbusr@192.168.1.94/smbusr/dest.txt"));  
8.               
9. byte [] buffer = new byte[1024];  
10. int c = 0;  
11. while ((c = fis.read(buffer)) != -1) {  
12.                 sfos.write(buffer);  
13.             }  
14. catch (SmbException e) {  
15.             e.printStackTrace();  
16. catch (MalformedURLException e) {  
17.             e.printStackTrace();  
18. catch (UnknownHostException e) {  
19.             e.printStackTrace();  
20. catch (IOException e) {  
21.             e.printStackTrace();  
22.         }  
23.           
24. finally {  
25. try {  
26.                 fis.close();  
27.                 sfos.close();  
28.                   
29. catch (IOException e) {  
30.                 e.printStackTrace();  
31.             }  
32.         }  
33.     }  

 
   
SAMBA的JAVA客户端JCIFS 

首页 
http://jcifs.samba.org/ 
下载文件 
jcifs-1.2.25b.zip 

下载的版本很新啊。能从MAVEN上搞到的版本如下pom.xml 
<dependency> 
<groupId>org.samba.jcifs</groupId> 
<artifactId>jcifs</artifactId> 
<version>1.2.15</version> 
</dependency> 

提供调用的static 工具类SambaUtil.java: 
package com.sillycat.api.commons.utils; 

import java.net.MalformedURLException; 

import jcifs.smb.SmbException; 
import jcifs.smb.SmbFile; 
import jcifs.smb.SmbFileInputStream; 
import jcifs.smb.SmbFileOutputStream; 

public class SambaUtil { 

public static void delete(String filepath, String username, String pwd) 
    { 
   SmbFile f = null; 
   try { 
    f = new SmbFile("smb://" + username + ":" + pwd + "@" 
      + filepath); 
    try { 
     if (f.exists()) { 
      f.delete(); 
     } 
    } catch (SmbException e) { 
     e.printStackTrace(); 
    } 
   } catch (MalformedURLException e) { 
    e.printStackTrace(); 
   } 
  
} 

public static boolean exists(String filepath, String username, String pwd) 
    throws Exception { 
   SmbFile file = new SmbFile("smb://" + username + ":" + pwd + "@" 
     + filepath); 
   try { 
    return file.exists(); 
   } catch (Exception e) { 
    e.printStackTrace(); 
    return false; 
   } 
} 

public static boolean filerename(String filepath, String newFilename, 
    String username, String pwd) { 
   try { 
    SmbFile f = new SmbFile("smb://" + username + ":" + pwd + "@" 
      + filepath); 
    if (f.isFile()) { 
     String str = filepath.substring(0, filepath.lastIndexOf("/")); 
     str = "smb://" + username + ":" + pwd + "@" + str + "/" 
       + newFilename; 
     f.renameTo(new SmbFile(str)); 
    } else if (f.isDirectory()) { 
     String str = filepath.substring(0, filepath.length() - 1); 
     str = filepath.substring(0, str.lastIndexOf("/")); 
     str = "smb://" + username + ":" + pwd + "@" + str + "/" 
       + newFilename; 
     f.renameTo(new SmbFile(str)); 
    } 
    return true; 
   } catch (Exception e) { 
    e.printStackTrace(); 
    return false; 
   } 
} 

public static void mkdir(String dir, String username, String pwd) { 
   try { 
    SmbFile f = new SmbFile("smb://" + username + ":" + pwd + "@" + dir); 
    if (!f.exists()) { 
     f.mkdir(); 
    } 
   } catch (Exception e) { 
    e.printStackTrace(); 
   } 
} 

public static void mkfile(String filepath, String username, String pwd) { 
   try { 
    SmbFile f = new SmbFile("smb://" + username + ":" + pwd + "@" 
      + filepath); 
    if (!f.exists()) { 
     f.createNewFile(); 
    } 
   } catch (Exception e) { 
    e.printStackTrace(); 
   } 
} 

public static void mkfile(String filepath, String username, String pwd, 
    String content) { 
   try { 
    SmbFile f = new SmbFile("smb://" + username + ":" + pwd + "@" 
      + filepath); 
    if (!f.exists()) 
     f.createNewFile(); 
    writefile(filepath, content, username, pwd); 
   } catch (Exception e) { 
    e.printStackTrace(); 
   } 
} 

public static String readfile(String filepath, String username, String pwd) { 
   StringBuffer sb = new StringBuffer(""); 
   try { 
    SmbFile f = new SmbFile("smb://" + username + ":" + pwd + "@" 
      + filepath); 
    if (f.exists() && f.isFile()) { 
     int length = f.getContentLength();// 得到文件的大小 
     byte buffer[] = new byte[length]; 

     SmbFileInputStream in = new SmbFileInputStream(f); 
     while ((in.read(buffer)) != -1) { 
      sb.append(new String(buffer)); 
     } 
     in.close(); 
    } 
   } catch (Exception e) { 
    e.printStackTrace(); 
   } 
   return sb.toString(); 
} 

public static boolean isdir(String filepath, String username, String pwd) 
    throws Exception { 
   String dir = "smb://" + username + ":" + pwd + "@" + filepath; 
   SmbFile f = new SmbFile(dir); 
   return f.isDirectory(); 
} 

public static void writefile(String filepath, String content, 
    String username, String pwd) { 
   try { 
    SmbFile to = new SmbFile("smb://" + username + ":" + pwd + "@" 
      + filepath); 
    SmbFileOutputStream out = new SmbFileOutputStream(to); 
    out.write(content.getBytes()); 
    out.close(); 
   } catch (Exception e) { 
    e.printStackTrace(); 
   } 

} 

} 

测试类SambaUtilTest.java: 
package com.sillycat.api.commons.utils; 

import junit.framework.TestCase; 

public class SambaUtilTest extends TestCase { 

protected void setUp() throws Exception { 
   super.setUp(); 
} 

protected void tearDown() throws Exception { 
   super.tearDown(); 
} 

public void testDummy() { 
   assertTrue(true); 
} 

public void testCreateDir() { 
   String dir = "www.sillycat.com/share/test1"; 
   SambaUtil.mkdir(dir, "guest", "guest"); 
   SambaUtil.mkfile(dir + "/test2.txt", "guest", "guest", "<html></html>中文hello world!"); 
   String tmp = SambaUtil.readfile(dir + "/test2.txt", "guest", "guest"); 
   System.out.println(tmp); 
   SambaUtil.delete(dir + "/test2.txt", "guest", "guest"); 
} 
} 


报错: 
jcifs.smb.SmbException: The network name cannot be found. 

原来是我的filepath写错了,写成www.sillycat.com/test1 
改成www.sillycat.com/share/test1就OK了 

报错: 
jcifs.smb.SmbException: The process cannot access the file because it is being used by another process. 

原来是方法里面的 
SmbFileInputStream in = new SmbFileInputStream(f); 
SmbFileOutputStream out = new SmbFileOutputStream(to); 
这个in 和 out 都要注意 close,我有一个忘记close了。。。汗