差異處

這裏顯示兩個版本的差異處。

連向這個比對檢視

java:jcifs [2017/08/19 23:33]
java:jcifs [2023/06/25 09:48] (目前版本)
行 1: 行 1:
 +{{tag>​java}}
 +====== JCIFS ======
 +===== Introduction =====
 +JCIFS是java-based存取網路芳鄰通訊協定的API。\\
 +\\
 +之所以接觸這個API,是因為好奇Windows管理工具[[http://​blog.xuite.net/​jyoutw/​xtech/​24607577-PsTools+%E4%B9%8B+PsExec+%E7%9A%84%E7%94%A8%E6%B3%95|psexec]],能將Local程式放到Remote並執行的做法。後來看到類似工具[[http://​www.poweradmin.com/​paexec/​|paexec]]程式碼,與經過自己的測試,發現原理是將程式複製到遠端的[[http://​en.wikipedia.org/​wiki/​Administrative_share|管理共享資料夾]],再透過WMI呼叫外部程式。\\
 +\\
 +接下來將說明我有使用的API。
 +===== How to? =====
 +首先至[[http://​jcifs.samba.org/​src/​|link]]下載library。接下來就是寫寫寫。
 +==== Create File ====
 +大部分的操作都可以透過SmbFile類別完成。而與遠端的機器認證,是透過[[http://​www.rfjh.ntpc.edu.tw/​web/​html/​teacher/​html/​ntlm.htm|NTLM通訊協定]]。
 +<code java>
 + 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);
 + }
 +</​code>​
 +如果有網域,可以使用
 +<code java>
 +new NtlmPasswordAuthentication(domain,​ user, passwd);
 +</​code>​
 +在建立完SmbFile物件後,剩下其實就和操作一般檔案無異。
 +<code java>
 + 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);​
 + }
 + }
 +</​code>​
 +最後是關閉串流的處理。
 +<code java>
 + private static void close(Closeable aCloseable){
 + if( aCloseable == null )
 + return;
 +
 + try {
 + aCloseable.close();​
 + } catch (IOException e) {
 + //  log exception
 + }
 + }
 +</​code>​
 +==== Delete File ====
 +刪除檔案:​
 +<code java>
 + public static void deleteFile(String aUser, String aPasswd, String aTarget) throws IOException {
 + SmbFile sFile = createSmbFile(aUser,​ aPasswd, aTarget);
 + sFile.delete();​
 + }
 +</​code>​
 +==== Exist ====
 +確認檔案是否存在:​
 +<code java>
 + public static boolean exists(String aUser, String aPasswd, String aTarget) throws IOException {
 + SmbFile sFile = createSmbFile(aUser,​ aPasswd, aTarget);
 + return sFile.exists();​
 + }
 +</​code>​
 +==== Copy File ====
 +複製本地檔案到遠端:​
 +<code java>
 + 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);​
 + }
 + }
 +</​code>​
 +複製遠端檔案到本地:​
 +<code java>
 +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);​
 + }
 + }
 +</​code>​
 +===== Test =====
 +簡單的寫了對檔案建立與複製的單元測試,這是對某台Win7機器的管理共享做存取。
 +<code java>
 +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));​
 + }
 +}
 +</​code>​
 +===== Summary =====
 +要將檔案複製到遠端,也可以透過
 +  - 在本地建立網芳或Samba Server,讓遠端由本地複製檔案。
 +  - 使用echo在遠端建立wget的VB Script,從本地的http server去wget檔案。
 +不管是以上兩種方法,或是透過管理共享,都是有可能因為使用者權限與安全性設定而失敗。只能見招拆招了。
 +===== Reference =====
 +  * [[http://​jcifs.samba.org/​|JCIFS official site]]
 +  * [[http://​sanjaal.com/​java/​875/​java-utilities/​java-tutorial-using-jcifs-to-copy-files-to-shared-network-drive-using-username-and-password/​|Copy File]]
 +  * [[http://​stackoverflow.com/​questions/​14749434/​how-to-copy-file-from-smb-share-to-local-drive-not-in-domain-with-jcifs|JCIFS with domain]]
 +
 +=====    =====
 +----
 +\\
 +~~DISQUS~~