Samba协议实现视频上传、远程播放

news2024/10/7 9:16:31

一、效果演示

扫码打开上传页面,上传进度可以全局筛选订单查看,上传过程中查看视频是本地视频(速度快),上传完成后再次打开是smb服务器视频(打开慢)

1494139297845084160

本文涉及demo参考下载

二、集成smbj

1、集成smbj

java使用samba协议,主要用到了smbj库

gradle集成

implementation 'com.hierynomus:smbj:0.10.0'

maven集成

<dependency>
    <groupId>com.hierynomus</groupId>
    <artifactId>smbj</artifactId>
    <version>0.10.0</version>
</dependency>

2、maven测试工程创建

直接在项目中测试比较麻烦,最好新建一个maven工程测试。如果初次新建maven项目,则需要配置仓库源为阿里镜像,并同步。

image-20230630144626652

settings.xml

<?xml version="1.0" encoding="UTF-8"?>
<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-aliyun</id>
            <mirrorOf>central</mirrorOf>
            <name>Nexus aliyun</name>
            <url>http://maven.aliyun.com/nexus/content/groups/public</url>
        </mirror>
    </mirrors>
</settings>

三、smb操作

1、初始化连接配置

如果有上传流的操作,则需要开启共享读写,否则会造成文件一直被暂用情况(当然也可以让这个客户端断开连接)

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();
    }
}

2、文件上传

/**
 * 上传文件到远程
 *
 * @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();
    }
}

3、创建远程文件夹

/**
 * 创建远程目录
 *
 * @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);
    }
}

4、下载远程文件

/**
 * 下载远程文件
 *
 * @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();
    }
}

5、服务器拷贝

这个是通过磁盘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);

6、更多功能与备注

更多功能:除了上述功能外,smb还支持list查看文件夹,删除文件夹、文件等

备注:在实际使用过程中,发现smbj库对于系统仍然有区别

1、macOS共享的smb:不支持服务器拷贝、不支持创建文件夹

2、linux共享的smb:一切正常

四、播放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:0429@192.168.1.114/mac/tempDir/测试.mp4";
intent.putExtra("videoPlayPath", path);
mContext.startActivity(intent);

VlcPlayerActivity相关android项目下载参考前面的"一、效果演示",内附demo下载链接

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/704208.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

写毕业论文之前一定要看的经验总结!!!

本文为笔者关于毕业论文的经验总结 如果本文有错误的地方 或者关于论文有什么更好的经验分享欢迎私信或者评论指出 打开word的格式标记 打开标尺 摘要 标题 目录 分页 页码 图片 表格 参考文献 打开word的格式标记 word格式标记并不是真的存在&#xff0c;只是帮你你修改word时…

嵌入式工作的前景:为什么嵌入式系统需求仍在增长

嵌入式系统的需求在过去几十年中一直稳步增长&#xff0c;并且预计在未来仍然会继续增加。嵌入式系统是指嵌入到其他设备或系统中的计算机系统&#xff0c;它们具有特定的功能和任务。这些系统广泛应用于汽车、消费电子产品、医疗设备、智能家居、工业自动化等领域。 随着科技…

Quiz 10: Tuples | Python for Everybody 配套练习_解题记录

文章目录 课程简介Quiz 10: Tuples 单选题&#xff08;1-11&#xff09;编程题Exercise 10.2 课程简介 Python for Everybody 零基础程序设计&#xff08;Python 入门&#xff09; This course aims to teach everyone the basics of programming computers using Python. 本课…

【软件测试】Java+selenium环境搭建

目录 1.下载Chrome浏览器&#xff0c;查看浏览器的版本 2.根据浏览器版本下载驱动 根据电脑版本下载驱动&#xff1a; 3.去maven仓库寻找selenium驱动 4.在idea中创建一个项目 1.在pom.xml中添加依赖 2.点击右侧刷新按钮 3.在Java下创建一个类Main 4.将以下代码写入 5.…

B061-ES6 NodeJS npm Vue

目录 ECMAScript6什么是ECMAScriptECMAScript历史语法申明变量解构表达式箭头函数模块化 npm引出nodejs安装VUEvue简介配置Terminalvue入门vue属性-elvue属性-datavue属性-methods vue架构认识vue表达式vue-表达式-基础vue-表达式-操作对象&数组 vue-指令v-text & v-ht…

软件工程师,入门下深度学习吧

概述 ChatGPT,英文全称为Chat Generative Pre-trained Transformer,是OpenAI研发的聊天机器人程序。ChatGPT是人工智能技术驱动的自然语言处理工具,它能够通过理解和学习人类的语言来进行对话,还能根据聊天的上下文进行互动,真正像人类一样来聊天交流。除此之外,还能进行…

kettle架构图

2、架构说明 1&#xff09;最底层的是kettle的核心引擎层&#xff0c;相关的jar在lib目录下。 2&#xff09;中间是开发层&#xff0c;在开发阶段我们接触最多的就是通过spoon进行开发&#xff0c;通过Spoon.bat或者spoon.sh即可启动客户端&#xff0c;开发文件调试之前要先保…

使用vtk创建立方体,设置顶点为不同颜色

引言 改示例为官网上的例子。创建了一个顶点是不同颜色的立方体。 示例 开发环境 使用QtCreator4.11.2,Qt5.14.2。使用的vtk9.2的库及其头文件。创建空项目。 示例代码 其pro文件中的内容&#xff1a; QT core guigreaterThan(QT_MAJOR_VERSION, 4): QT widgets…

【半监督图像分类 ICLR 2023】FreeMatch

【半监督图像分类 ICLR 2023】FreeMatch 论文题目&#xff1a;FREEMATCH: SELF-ADAPTIVE THRESHOLDING FOR SEMI-SUPERVISED LEARNING 中文题目&#xff1a;Freematch&#xff1a;用于半监督学习的自适应阈值 论文链接&#xff1a;https://arxiv.org/abs/2205.07246 论文代码&a…

数字经济下的架构新图景—2023架构·可持续未来峰会(北京主会场)成功举办!

2023 年 6 月 29日&#xff0c;由The Open Group主办的2023架构可持续未来峰会&#xff08;北京主会场&#xff09;在机械工业出版社圆满落幕。 本次大会以“可持续未来”为主题&#xff0c;采取13&#xff0c;即北京主会场上海/成都/深圳三个城市峰会场模式&#xff0c;聚焦架…

android h5 宿舍报修管理系统myeclipse开发mysql数据库编程服务端java计算机程序设计

一、源码特点 android h5 宿舍报修管理系统是一套完善的WEBandroid设计系统&#xff0c;对理解JSP java&#xff0c;安卓app编程开发语言有帮助&#xff08;系统采用web服务端APP端 综合模式进行设计开发&#xff09;&#xff0c;系统具有完整的 源代码和数据库&#xff0c;系…

idea 修改Tool Windows后新建项目又恢复默认设置

我们可能会根据自己的喜好修改idea的工具窗口,但是每次新建项目它又会重置了,解决办法如下:

vscode C++开发记录

vscode C开发记录 插件管理Linux 平台针对编译好的程序进行 Dedug 插件管理 Linux 平台 针对编译好的程序进行 Dedug 右击源文件后&#xff0c;添加debug 配置 Add Debug Configuration 这是一个示例的调试配置文件&#xff0c;用于在VS Code中使用GDB调试已经编译好的程序 …

Sublime Text 初步使用

Sublime Text &#xff0c;最初被设计为一个具有丰富扩展功能的Vim。 Sublime Text具有漂亮的用户界面和强大的功能&#xff0c;例如代码缩略图&#xff0c;Python的插件&#xff0c;代码段等。还可自定义键绑定&#xff0c;菜单和工具栏。Sublime Text 的主要功能包括&#xf…

Vue常见面试题整理

一、对于MVVM的理解&#xff1f; MVVM是Model-View-ViewModel的缩写。 Model&#xff1a;代表数据模型&#xff0c;也可以在Model中定义数据修改和操作的业务逻辑。View&#xff1a;代表UI组件&#xff0c;它负责将数据模型转化成UI展现出来。ViewModel&#xff1a;监听模型数…

Equivariant Graph Neural Networks

论文链接&#xff1a;https://arxiv.org/abs/2102.09844 一种新模型来学习与旋转、平移、反射和排列等变的图神经网络&#xff0c;称为 E(n)-等变图神经网络 (EGNN) 尽管深度学习在很大程度上取代了手工制作的特征&#xff0c;但许多进步严重依赖于深度神经网络中的归纳偏差。…

linux watch命令

在Linux中&#xff0c;有时需要每隔一段时间比如一秒或者两秒刷新一次&#xff0c;这时就可以使用watch 命令。如图&#xff1a; 每隔两秒刷新查看一下磁盘使用情况。

Chrome DevTools常用功能指南

目录 Elements Styles DOM结构 增删属性 模拟元素的伪状态&#xff0c;方便调试 Computed Layout Event Listeners Network Application 资源列表&#xff08;可改&#xff09;本地存储Cookie、WebStorage&#xff08;localStorage、sessionStorage&#xff09; Sourc…

【Linux进程】进程状态 {进程状态的介绍,进程状态的转换,Linux中的进程状态,浅度睡眠VS深度睡眠,僵尸进程VS孤儿进程,调度器的作用}

进程状态 一、基本进程状态 1.1 进程状态介绍 创建状态&#xff1a;当一个进程被创建时&#xff0c;它处于创建状态。在这个阶段&#xff0c;操作系统为进程分配必要的资源&#xff08;将代码和数据拷贝到内存&#xff0c;创建PCB结构体等&#xff09;&#xff0c;并为其分配一…

SpringBoot开发Restful风格的接口实现CRUD功能

基于SpringBoot开发一个Restful接口 前言一、什么是SpringBoot&#xff1f;二、实战---基于SpringBoot开发一个Restful接口1.开发前的准备工作1.1 添加相关依赖 &#xff08;pom文件&#xff09; 1.2 创建相关数据库和表1.3 数据库配置文件 2.实战开发---代码逻辑2.1 实体类2.2…