在Java程序中讀寫windows共享文件夾


摘要 使用Java通過JCIFS框架讀寫共享文件夾,使用SMB協議,並支持域認證。

項目常常需要有訪問共享文件夾的需求,例如讀取共享文件夾存儲的視頻、照片和PPT等文件。那么如何使用Java讀寫Windows共享文件夾呢?

使用Java訪問擁有全部讀寫權限的共享文件夾比較簡單,和普通的目錄沒有什么區別。但是,如果從Linux服務器訪問一個windows服務器上需要用戶名和密碼驗證的共享文件夾,就需要一點點小技巧了。這里介紹一個開源的庫JCIFS,他可以輕松滿足此需求。

JCIFS是使用Java語言開發的一款開源框架,通過SMB協議訪問遠程共享文件夾,就像訪問本地文件夾一樣,簡簡單單。她同時支持Windows和Linux共享文件夾,不過,Linux共享文件夾需要安裝Samba服務軟件(官網:http://www.samba.org/)。

另外,通過掛載該共享文件夾到Linux服務器下也可以實現,此時不需要借助SMB協議,對此,這里不做介紹,感興趣的童鞋可以去問問度娘。

言歸正傳,maven依賴如下:

<!-- https://mvnrepository.com/artifact/org.samba.jcifs/jcifs -->
<dependency>
    <groupId>org.samba.jcifs</groupId>
    <artifactId>jcifs</artifactId>
    <version>1.3.3</version>
</dependency>

SMB(Server Message Block)通信協議是微軟(Microsoft)和英特爾(Intel)在1987年制定的協議,主要是作為Microsoft網絡的通訊協議。SMB 是在會話層(session layer)和表示層(presentation layer)以及小部分應用層(application layer)的協議。通過設置“NetBIOS over TCP/IP”使得Samba不但能與局域網絡主機分享資源,還能與全世界的電腦分享資源。

代碼示例:

 
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

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

public class SmbFileUtil {

    private static Logger log = LoggerFactory.getLogger(SmbFileUtil.class);

    private static String USER_DOMAIN = "yourDomain";
    private static String USER_ACCOUNT = "yourAccount";
    private static String USER_PWS = "yourPassword";

    public static void main(String[] args) throws Exception {

        // remoteUrl 格式示例 【smb://132.20.2.33/CIMPublicTest/】
        // 目錄
        String shareDir = "smb:// 132.20.2.33/CIMPublicTest/";
        listFiles(shareDir);
        
    }

    /**
     * @Title listFiles
     * @Description 遍歷指定目錄下的文件
     * @date 2019-01-11 09:56
     */
    private static void listFiles(String shareDirectory) throws Exception {
        long startTime = System.currentTimeMillis();

        // 域服務器驗證
        NtlmPasswordAuthentication auth = new NtlmPasswordAuthentication(USER_DOMAIN, USER_ACCOUNT,
                USER_PWS);
        SmbFile remoteFile = new SmbFile(shareDirectory, auth);
        log.info("遠程共享目錄訪問耗時:【{}】", System.currentTimeMillis() - startTime);

        if (remoteFile.exists()) {
            SmbFile[] files = remoteFile.listFiles();
            remoteFile.listFiles(shareDirectory);
            
            for (SmbFile f : files) {
                log.info(f.getName());
            }
        } else {
            log.info("文件不存在");
        }
    }
}
 

NtlmPasswordAuthentication類用於域認證,需要三個參數, 第一個是域名,如果沒有,就賦值null, 第二個是用戶名,第三個是密碼。下面列舉SMB協議的兩個應用場景。SmbFile類和Java的File類十分相似,使用其對象可以處理遠程共享文件的讀寫。

 
    /**
     * @Title smbGet
     * @Param shareUrl 共享目錄中的文件路徑,如smb://132.20.2.33/CIMPublicTest/eg.txt
     * @Param localDirectory 本地目錄,如tempStore/smb
     */
    public static void smbGet(String shareUrl, String localDirectory) throws Exception {
        NtlmPasswordAuthentication auth = new NtlmPasswordAuthentication(USER_DOMAIN, USER_ACCOUNT,
                USER_PWS);
        SmbFile remoteFile = new SmbFile(shareUrl, auth);
        if (!remoteFile.exists()) {
            log.info("共享文件不存在");
            return;
        }
        // 有文件的時候再初始化輸入輸出流
        InputStream in = null;
        OutputStream out = null;
        log.info("下載共享目錄的文件 shareUrl 到 localDirectory");
        try {
            String fileName = remoteFile.getName();
            File localFile = new File(localDirectory + File.separator + fileName);
            File fileParent = localFile.getParentFile();
            if (null != fileParent && !fileParent.exists()) {
                fileParent.mkdirs();
            }
            in = new BufferedInputStream(new SmbFileInputStream(remoteFile));
            out = new BufferedOutputStream(new FileOutputStream(localFile));
            byte[] buffer = new byte[1024];
            while (in.read(buffer) != -1) {
                out.write(buffer);
                buffer = new byte[1024];
            }
            out.flush(); //刷新緩沖區輸出流

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            out.close();
            in.close();
        }
    }

    /**
     * 
     * @Title smbPut
     * @Description 向共享目錄上傳文件
     * @Param shareDirectory 共享目錄
     * @Param localFilePath 本地目錄中的文件路徑
     * @date 2019-01-10 20:16
     */
    public static void smbPut(String shareDirectory, String localFilePath) {
        InputStream in = null;
        OutputStream out = null;
        try {
            File localFile = new File(localFilePath);

            String fileName = localFile.getName();
            SmbFile remoteFile = new SmbFile(shareDirectory + "/" + fileName);
            in = new BufferedInputStream(new FileInputStream(localFile));
            out = new BufferedOutputStream(new SmbFileOutputStream(remoteFile));
            byte[] buffer = new byte[1024];
            while (in.read(buffer) != -1) {
                out.write(buffer);
                buffer = new byte[1024];
            }
            out.flush();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                out.close();
                in.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM