[CIFS/SMB]关于 windows 之间传输文件的Java代码实现

      关于windows主机之间传输文件,在不依赖于外部第三方服务的情况下,大多会选择 SMB/CIFS协议;关于 SMB/CIFS 协议相关的内容大家可以自行查阅微软官方文档;

      目前本人测试自己的主机到 VMWare中的win7虚拟机传输文件,亲测速率最快可达到 9MB/s(具体实际使用传输速度情况,视硬件及网络带宽而定);

关键实现代码如下所示:

package com.morpheus.transfer.win;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.util.Optional;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.morpheus.transfer.common.HostVO;
import com.morpheus.transfer.utils.CommonUtil;

import jcifs.UniAddress;
import jcifs.smb.NtlmPasswordAuthentication;
import jcifs.smb.SmbException;
import jcifs.smb.SmbFile;
import jcifs.smb.SmbFileOutputStream;
import jcifs.smb.SmbSession;

public class WinTransferService {
	private static final Logger LOGGER = LoggerFactory.getLogger(WinTransferService.class);
	public static final String KEY_JCIFS_SMB_CLIENT_DFS_DISABLED = "jcifs.smb.client.dfs.disabled";

	private HostVO hostVO = null;

	public WinTransferService(HostVO hostVO) {
		this.hostVO = hostVO;
	}

	private boolean validParams() {
		boolean notEmpty = CommonUtil.isAllNotEmpty(StringUtils.trimToEmpty(this.hostVO.getValidIP()),
				StringUtils.trimToEmpty(this.hostVO.getUserName()), StringUtils.trimToEmpty(this.hostVO.getUserPwd()));
		return notEmpty;
	}

	private boolean validParams(String... params) {
		boolean notEmpty = CommonUtil.isAllNotEmpty(StringUtils.trimToEmpty(this.hostVO.getValidIP()),
				StringUtils.trimToEmpty(this.hostVO.getUserName()), StringUtils.trimToEmpty(this.hostVO.getUserPwd()));
		boolean notEmptyParams = CommonUtil.isAllNotEmpty(params);
		return notEmpty && notEmptyParams;
	}

	public boolean loginToRemote() {
		if (!this.validParams()) {
			throw new IllegalArgumentException("Invalid host ip/userName/userPwd");
		}
		String domain = this.hostVO.getDomain();
		String userName = this.hostVO.getUserName();
		String userPwd = this.hostVO.getUserPwd();
		try {
			UniAddress uniDC = UniAddress.getByName(this.hostVO.getValidIP());
			NtlmPasswordAuthentication auth = new NtlmPasswordAuthentication(domain, userName, userPwd);
			SmbSession.logon(uniDC, auth);
			SmbFile smbFile = new SmbFile(String.format("cifs://%s/C$/", new Object[] { this.hostVO.getValidIP() }),
					auth);
			String[] files = smbFile.list();
			files = Optional.ofNullable(files).orElse(new String[0]);
			return files.length > 0;
		} catch (Throwable th) {
			LOGGER.error("WinTransferService.loginToRemote()	Throwable", th);
		}
		return false;
	}

	public InputStream readFromRemote(String remoteFile) throws IOException {
		if (!this.validParams(remoteFile)) {
			throw new IllegalArgumentException("Invalid host ip/userName/userPwd");
		}
		String domain = this.hostVO.getDomain();
		String userName = this.hostVO.getUserName();
		String userPwd = this.hostVO.getUserPwd();

		NtlmPasswordAuthentication auth = new NtlmPasswordAuthentication(domain, userName, userPwd);
		remoteFile = StringUtils.trimToEmpty(remoteFile);
		remoteFile = remoteFile.replace("\\", "/").replace(":", "$");
		SmbFile smbFile = new SmbFile(
				String.format("cifs://%s/%s", new Object[] { this.hostVO.getValidIP(), remoteFile }), auth);
		if (smbFile.exists()) {
			return smbFile.getInputStream();
		}
		return new ByteArrayInputStream("ReadFromRemoteError".getBytes());
	}

	public void createRemoteDir(String remoteDir, boolean deleteExist, NtlmPasswordAuthentication auth)
			throws MalformedURLException, SmbException {
		String remoteRelativePath = remoteDir.replace("\\", "/").replace(":", "$") + "/";
		String hostIP = this.hostVO.getValidIP();
		SmbFile smbDir = new SmbFile(String.format("cifs://%s/%s", new Object[] { hostIP, remoteRelativePath }), auth);
		if (deleteExist) {
			if (smbDir.exists()) {
				smbDir.delete();
			}
		}
		if (!smbDir.exists()) {
			smbDir.mkdirs();
		}
	}

	public void transferToRemote(String localPath, String remoteDir) throws IOException {
		if (!this.validParams(localPath, remoteDir)) {
			throw new IllegalArgumentException("Invalid host ip/userName/userPwd");
		}
		File localFile = new File(localPath);

		String domain = this.hostVO.getDomain();
		String userName = this.hostVO.getUserName();
		String userPwd = this.hostVO.getUserPwd();

		LOGGER.info("WinTransferService.transferToRemote()	begin: localPath={}, remoteDir={}", localPath, remoteDir);
		System.setProperty(KEY_JCIFS_SMB_CLIENT_DFS_DISABLED, String.valueOf(true));
		jcifs.Config.setProperty(KEY_JCIFS_SMB_CLIENT_DFS_DISABLED, String.valueOf(true));
		NtlmPasswordAuthentication auth = new NtlmPasswordAuthentication(domain, userName, userPwd);
		if (localFile.isFile()) {
			remoteDir = remoteDir.replace("\\", "/") + "/";
			this.createRemoteDir(remoteDir, false, auth);
			this.uploadFileWithSmb(localFile, remoteDir, auth);
		} else if (localFile.isDirectory()) {
			remoteDir = remoteDir.replace("\\", "/") + "/" + localFile.getName();
			this.createRemoteDir(remoteDir, true, auth);
			this.uploadDirWithSmb(localFile, remoteDir, auth);
		}
		LOGGER.info("WinTransferService.transferToRemote()	end: localPath={}, remoteDir={}", localPath, remoteDir);
	}

	public void uploadFileWithSmb(File localFile, String remoteDir, NtlmPasswordAuthentication auth) {
		FileInputStream fileInputStream = null;
		SmbFileOutputStream smbFileOutputStream = null;
		try {
			String remoteRelativePath = remoteDir.replace("\\", "/").replace(":", "$") + "/" + localFile.getName();
			SmbFile smbFile = new SmbFile(
					String.format("cifs://%s/%s", new Object[] { this.hostVO.getValidIP(), remoteRelativePath }), auth);
			smbFileOutputStream = new SmbFileOutputStream(smbFile);
			fileInputStream = new FileInputStream(localFile);
			IOUtils.copyLarge(fileInputStream, smbFileOutputStream);
		} catch (Throwable th) {
			LOGGER.error("TransferService.putFileWithSamba()	Throwable", th);
		} finally {
			IOUtils.closeQuietly(fileInputStream);
			IOUtils.closeQuietly(smbFileOutputStream);
		}
	}

	public void uploadDirWithSmb(File localDir, String remoteDir, NtlmPasswordAuthentication auth) throws IOException {
		File[] files = localDir.listFiles();
		files = Optional.ofNullable(files).orElse(new File[0]);
		for (File file : files) {
			if (file.isDirectory()) {
				String relativeDestFile = remoteDir.replace("\\", "/").replace(":", "$") + "/" + file.getName();
				SmbFile smbFile = new SmbFile(
						String.format("cifs://%s/%s", new Object[] { this.hostVO.getValidIP(), relativeDestFile }),
						auth);
				if (!smbFile.exists()) {
					smbFile.mkdirs();
				} else if (smbFile.isDirectory()) {
					smbFile.delete();
				}
				this.uploadDirWithSmb(file, remoteDir + "/" + file.getName(), auth);
			} else if (file.isFile()) {
				FileInputStream fileInputStream = null;
				SmbFileOutputStream smbFileOutputStream = null;
				try {
					String relativeDestFile = remoteDir.replace("\\", "/").replace(":", "$") + "/" + file.getName();
					SmbFile smbFile = new SmbFile(
							String.format("cifs://%s/%s", new Object[] { this.hostVO.getValidIP(), relativeDestFile }),
							auth);
					smbFileOutputStream = new SmbFileOutputStream(smbFile);
					fileInputStream = new FileInputStream(file);
					IOUtils.copyLarge(fileInputStream, smbFileOutputStream);
				} finally {
					IOUtils.closeQuietly(fileInputStream);
					IOUtils.closeQuietly(smbFileOutputStream);
				}
			}
		}
	}
}

可以将文件传输封装成异步任务,以便多线程上传,如下所示:

package com.morpheus.transfer.win;

import java.util.concurrent.Callable;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;

import com.alibaba.fastjson.JSONObject;
import com.morpheus.transfer.common.HostVO;
import com.morpheus.transfer.utils.JSONUtil;

public class TransferJob implements Callable<JSONObject> {
	private static final Logger LOGGER = LoggerFactory.getLogger(TransferJob.class);

	private WinTransferService winTransferService = null;

	private String localDir = null;
	private String remoteDir = null;

	public TransferJob(HostVO hostVO, String localDir, String remoteDir) {
		this.winTransferService = new WinTransferService(hostVO);
		this.localDir = localDir;
		this.remoteDir = remoteDir;
	}

	@Override
	public JSONObject call() throws Exception {
		JSONObject resJSON = new JSONObject();
		try {
			boolean login = this.winTransferService.loginToRemote();
			if (login) {
				this.winTransferService.transferToRemote(this.localDir, this.remoteDir);
				resJSON = JSONUtil.createResult(resJSON, true, HttpStatus.OK.value(), "TransferFinished");
			}
		} catch (Throwable th) {
			LOGGER.error("TransferJob.call()	Throwable", th);
			resJSON = JSONUtil.createResult(resJSON, true, HttpStatus.OK.value(), "TransferError");
		}
		return resJSON;
	}
}

 

转载于:https://my.oschina.net/morpheusWB/blog/3000761

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值