扫码打开上传页面,上传进度可以全局筛选订单查看,上传过程中查看视频是本地视频(速度快),上传完成后再次打开是smb服务器视频(打开慢)
本文涉及demo参考下载
java使用samba协议,主要用到了smbj库
gradle集成
implementation 'com.hierynomus:smbj:0.10.0'
maven集成
<dependency>
<groupId>com.hierynomusgroupId>
<artifactId>smbjartifactId>
<version>0.10.0version>
dependency>
直接在项目中测试比较麻烦,最好新建一个maven工程测试。如果初次新建maven项目,则需要配置仓库源为阿里镜像,并同步。
settings.xml
<settings xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/SETTINGS/1.2.0"
xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.2.0 https://maven.apache.org/xsd/settings-1.2.0.xsd">
<mirrors>
<mirror>
<id>nexus-aliyunid>
<mirrorOf>centralmirrorOf>
<name>Nexus aliyunname>
<url>http://maven.aliyun.com/nexus/content/groups/publicurl>
mirror>
mirrors>
settings>
如果有上传流的操作,则需要开启共享读写,否则会造成文件一直被暂用情况(当然也可以让这个客户端断开连接)
public static void main(String[] args) throws Exception {
String ip = "192.168.1.114";
String userName = "";
String password = "";
String shareDir = "share";
SMBClient client = new SMBClient();
try (Connection connection = client.connect(ip)) {
AuthenticationContext ac = new AuthenticationContext(userName, password.toCharArray(), "");
Session session = connection.authenticate(ac);
// Connect to Share
try (DiskShare share = (DiskShare) session.connectShare(shareDir)) {
Set<FileAttributes> fileAttributes = new HashSet<>();
fileAttributes.add(FileAttributes.FILE_ATTRIBUTE_NORMAL);
fileAttributes.add(FileAttributes.FILE_ATTRIBUTE_ARCHIVE);
Set<SMB2CreateOptions> createOptions = new HashSet<>();
createOptions.add(SMB2CreateOptions.FILE_NO_COMPRESSION);
createOptions.add(SMB2CreateOptions.FILE_RANDOM_ACCESS);
// 共享读、共享写
Set<SMB2ShareAccess> smb2ShareAccesses = new HashSet<>();
smb2ShareAccesses.add(SMB2ShareAccess.FILE_SHARE_WRITE);
smb2ShareAccesses.add(SMB2ShareAccess.FILE_SHARE_READ);
// 连接成功
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 上传文件到远程
*
* @param host IP地址
* @param username 用户名
* @param password 用户密码
* @param path 共享目录
* @param innerDir 远程内部文件夹
* @param localFileName 本地文件
*/
public static void uploadFile(String host, String username, String password, String path, String innerDir, String localFileName) {
DiskShare share = getDiskShare(host, username, password, path);
try {
// 如果目录不存在,逐层创建
createRemoteDir(share, innerDir);
Set<AccessMask> accessMasks = new HashSet<>();
accessMasks.add(AccessMask.FILE_ADD_FILE);
Set<FileAttributes> attributes = new HashSet<>();
attributes.add(FileAttributes.FILE_ATTRIBUTE_NORMAL);
Set<SMB2ShareAccess> smb2ShareAccesses = new HashSet<>();
smb2ShareAccesses.add(SMB2ShareAccess.FILE_SHARE_WRITE);
smb2ShareAccesses.add(SMB2ShareAccess.FILE_SHARE_READ);
Set<SMB2CreateOptions> smb2CreateOptions = new HashSet<>();
smb2CreateOptions.add(SMB2CreateOptions.FILE_RANDOM_ACCESS);
// 文件名称: "tempDir/测试.mp4"
String fileName = innerDir + "/" + localFileName.substring(localFileName.lastIndexOf("/") + 1);
com.hierynomus.smbj.share.File openFile = share.openFile(fileName, accessMasks, attributes, smb2ShareAccesses, SMB2CreateDisposition.FILE_OVERWRITE_IF, smb2CreateOptions);
OutputStream oStream = openFile.getOutputStream();
BufferedInputStream in = new BufferedInputStream(new FileInputStream(localFileName));
byte[] buffer = new byte[1024*1024];
int len = 0; //Read length
while ((len = in.read(buffer, 0, buffer.length)) != -1) {
oStream.write(buffer, 0, len);
}
oStream.flush();
oStream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 创建远程目录
*
* @param share
* @param dirName
*/
private static void createRemoteDir(DiskShare share, String dirName) {
// 是否已存在
if (share.folderExists(dirName)) {
return;
}
// 目录不存在,逐层创建
String[] fileNameArr = dirName.split("/");
String tempDirName = ""; // 逐层目录
for (String fileName : fileNameArr) {
tempDirName += fileName + "/"; // 下一层目录
if (share.folderExists(tempDirName)) {
continue;
}
System.out.println("目录: " + tempDirName + " 不存在,即将创建");
share.mkdir(tempDirName);
}
}
/**
* 下载远程文件
*
* @param host IP地址
* @param username 用户名
* @param password 用户密码
* @param path 共享目录
* @param remoteFile 远程文件, 可以是具体的文件,可以是匹配的文件
* @param localDir 本地目标目录
*/
public static void downloadFile(String host, String username, String password, String path, String remoteFile, String localDir) {
DiskShare share = getDiskShare(host, username, password, path);
// 添加文件夹分隔符
localDir = checkDirEnd(localDir);
try {
// 文件夹是否存在,创建本地目录
createLocalDirIfNotExist(localDir);
String remoteDir = "";
for (FileIdBothDirectoryInformation f : share.list(remoteDir, remoteFile)) {
String filePath = f.getFileName();
String dstPath = localDir + f.getFileName();
FileOutputStream fos = new FileOutputStream(dstPath);
BufferedOutputStream bos = new BufferedOutputStream(fos);
if (share.fileExists(filePath)) {
System.out.println("正在下载文件: " + f.getFileName());
com.hierynomus.smbj.share.File smbFileRead = share.openFile(filePath, EnumSet.of(AccessMask.GENERIC_READ), null, SMB2ShareAccess.ALL, SMB2CreateDisposition.FILE_OPEN, null);
InputStream in = smbFileRead.getInputStream();
byte[] buffer = new byte[4096];
int len = 0;
while ((len = in.read(buffer, 0, buffer.length)) != -1) {
bos.write(buffer, 0, len);
}
bos.flush();
bos.close();
System.out.println("文件下载成功, 保存在 " + dstPath);
} else {
System.out.println("文件 " + filePath + " 不存在");
}
}
} catch (Exception e) {
System.out.println("文件下载失败");
e.printStackTrace();
}
}
这个是通过磁盘IO,没有经过网络,速度可以达到几百MB每秒
String filePath1 = "wenjing/test/1.mp4";
File file1 = share.openFile(filePath1, EnumSet.of(AccessMask.GENERIC_READ), fileAttributes, SMB2ShareAccess.ALL, SMB2CreateDisposition.FILE_OPEN_IF, createOptions);
String filePath2 = "wenjing/test/1_jdk15.mp4";
File file2 = share.openFile(filePath2, EnumSet.of(AccessMask.GENERIC_WRITE), fileAttributes, SMB2ShareAccess.ALL, SMB2CreateDisposition.FILE_CREATE, createOptions);
file1.remoteCopyTo(file2);
更多功能:除了上述功能外,smb还支持list查看文件夹,删除文件夹、文件等
备注:在实际使用过程中,发现smbj库对于系统仍然有区别
1、macOS共享的smb:不支持服务器拷贝、不支持创建文件夹
2、linux共享的smb:一切正常
播放smb链接视频需要用到vlc库,这个库相对较大(大概三十几MB),但是体验比自己写的流稳定。
implementation 'com.yyl.vlc:vlc-android-sdk:3.3.0'
跳转播放页面
Intent intent = new Intent(mContext, VlcPlayerActivity.class);
String path = "smb://dabaojiqi:[email protected]/mac/tempDir/测试.mp4";
intent.putExtra("videoPlayPath", path);
mContext.startActivity(intent);
VlcPlayerActivity相关android项目下载参考前面的"一、效果演示",内附demo下载链接