Introduction
JCIFS是java-based存取網路芳鄰通訊協定的API。
之所以接觸這個API,是因為好奇Windows管理工具psexec,能將Local程式放到Remote並執行的做法。後來看到類似工具paexec程式碼,與經過自己的測試,發現原理是將程式複製到遠端的管理共享資料夾,再透過WMI呼叫外部程式。
接下來將說明我有使用的API。
How to?
首先至link下載library。接下來就是寫寫寫。
Create File
大部分的操作都可以透過SmbFile類別完成。而與遠端的機器認證,是透過NTLM通訊協定。
private static NtlmPasswordAuthentication createAuth(String aUser, String aPasswd){ StringBuffer sb = new StringBuffer(aUser); sb.append(':').append(aPasswd); return new NtlmPasswordAuthentication(sb.toString()); } public static SmbFile createSmbFile(String aUser, String aPasswd, String aTarget) throws IOException { NtlmPasswordAuthentication auth = createAuth(aUser, aPasswd); return new SmbFile(aTarget, auth); }
如果有網域,可以使用
new NtlmPasswordAuthentication(domain, user, passwd);
在建立完SmbFile物件後,剩下其實就和操作一般檔案無異。
public static void createFile(String aUser, String aPasswd, String aTarget, String aContent) throws IOException { SmbFile sFile = createSmbFile(aUser, aPasswd, aTarget); SmbFileOutputStream sfos = null; try { sfos = new SmbFileOutputStream(sFile); sfos.write(aContent.getBytes()); } finally { close(sfos); } }
最後是關閉串流的處理。
private static void close(Closeable aCloseable){ if( aCloseable == null ) return; try { aCloseable.close(); } catch (IOException e) { // log exception } }
Delete File
刪除檔案:
public static void deleteFile(String aUser, String aPasswd, String aTarget) throws IOException { SmbFile sFile = createSmbFile(aUser, aPasswd, aTarget); sFile.delete(); }
Exist
確認檔案是否存在:
public static boolean exists(String aUser, String aPasswd, String aTarget) throws IOException { SmbFile sFile = createSmbFile(aUser, aPasswd, aTarget); return sFile.exists(); }
Copy File
複製本地檔案到遠端:
public static void copyFileTo(String aUser, String aPasswd, String aSource, String aTarget) throws IOException { SmbFile sFile = createSmbFile(aUser, aPasswd, aTarget); SmbFileOutputStream sfos = null; FileInputStream fis = null; try { sfos = new SmbFileOutputStream(sFile); fis = new FileInputStream(new File(aSource)); byte[] buf = new byte[1024]; int len; while(( len = fis.read(buf) )> 0 ){ sfos.write(buf, 0, len); } } finally { close(sfos); close(fis); } }
複製遠端檔案到本地:
public static void copyFileFrom(String aUser, String aPasswd, String aSource, String aTarget) throws IOException { SmbFile sFile = createSmbFile(aUser, aPasswd, aSource); SmbFileInputStream sfis = null; FileOutputStream fos = null; try { sfis = new SmbFileInputStream(sFile); fos = new FileOutputStream(new File(aTarget)); byte[] buf = new byte[1024]; int len; while(( len = sfis.read(buf) )> 0 ){ fos.write(buf, 0, len); } } finally { close(sfis); close(fos); } }
Test
簡單的寫了對檔案建立與複製的單元測試,這是對某台Win7機器的管理共享做存取。
public class SmbFileUtilTest { private String targetFolder = "smb://192.168.1.25/admin$/"; private String user = "administrator"; private String passwd = "123456"; private String remoteTmpFile = null; private String localTmpFile = null; @After public void tearDown() throws IOException{ if( remoteTmpFile != null ){ SmbFileUtil.deleteFile(user, passwd, remoteTmpFile); assertFalse(SmbFileUtil.exists(user, passwd, remoteTmpFile)); } if( localTmpFile != null ){ new File(localTmpFile).delete(); } } @Test public void copyFile() throws IOException{ remoteTmpFile = targetFolder+"temp.txt"; localTmpFile = "temp.tmp"; SmbFileUtil.copyFileTo(user, passwd, "libs/jcifs-1.3.18.jar", remoteTmpFile); assertTrue(SmbFileUtil.exists(user, passwd, remoteTmpFile)); SmbFileUtil.copyFileFrom(user, passwd, remoteTmpFile, localTmpFile); File localFile = new File(localTmpFile); assertTrue(localFile.exists()); assertEquals(new File("libs/jcifs-1.3.18.jar").length(), localFile.length()); } @Test public void createFile() throws IOException{ remoteTmpFile = targetFolder+"temp.txt"; SmbFileUtil.createFile(user, passwd , remoteTmpFile, "test"); assertTrue(SmbFileUtil.exists(user, passwd, remoteTmpFile)); } }
Summary
要將檔案複製到遠端,也可以透過
- 在本地建立網芳或Samba Server,讓遠端由本地複製檔案。
- 使用echo在遠端建立wget的VB Script,從本地的http server去wget檔案。
不管是以上兩種方法,或是透過管理共享,都是有可能因為使用者權限與安全性設定而失敗。只能見招拆招了。
留言
張貼留言