java大视频分片上传

实现原理,前端控制每次上传1mb,后端接受1mb,并记录该分片下标,返回给前端还未上传的下标,直到所有的都上传完成

controller

@ApiOperation(value = "上传视频", notes = "上传视频", httpMethod = "POST", response = WebResult.class)
@PostMapping(value = "/uploadVideo", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)//
public AjaxResult uploadVideo(@RequestParam(name = "file") MultipartFile file,@RequestParam(name = "chunkIndex") Integer chunkIndex,@RequestParam(name = "md5") String md5,@RequestParam(name = "totalFileSize") Long totalFileSize,@RequestParam(name = "fileName") String fileName,@RequestParam(name = "userName") String userName,HttpServletRequest request) throws Exception {if (null == file || file.isEmpty()) {return AjaxResult.error("文件内容不能为空!");}return fileSystemService.uploadVideo(file, chunkIndex, md5, fileName, userName);}

service

public AjaxResult uploadVideo(MultipartFile file, Integer chunkIndex, String md5, String fileName, String userName) throws IOException {//创建存放文件夹String date = DateTime.now().toString("yyyyMMdd");String dirPath = ConstantUtils.FILE_VIDEO_PATH + userName + "/" + date + "/" + md5 + "/";File dirFile = new File(dirPath);if (!dirFile.exists()){dirFile.mkdirs();}//分区文件String relativeFilePath = dirPath + fileName;File tempFile = new File(relativeFilePath);RandomAccessFile rw = new RandomAccessFile(tempFile, "rw");//定位到分片的偏移量rw.seek(Long.parseLong(ConstantUtils.FILE_VIDEO_CHUNK_SIZE) * chunkIndex);//写入分片数据rw.write(file.getBytes());//关闭流rw.close();//读取已经分片的集合Set<Object> hasChunkList = new HashSet<>();String hasChunkKey = ConstantUtils.CHUNK_PREFIX + md5;if (redisHelper.hasKey(hasChunkKey)){Object o = redisHelper.get(hasChunkKey);JSONArray array = JSONUtil.parseArray(o);hasChunkList.addAll(array);}hasChunkList.add(chunkIndex);//最新分片下标跟新到redisredisHelper.set(hasChunkKey,hasChunkList);HashMap<String, Object> map = new HashMap<>();map.put("url",userName + "/" + date + "/" + md5 + "/" + fileName);map.put("hasList",hasChunkList);return AjaxResult.success(map);}

ConstantUtils

package com.ruoyi.file.utils;import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;/*** @author csb* @description: 获取配置文件常量数据* @date 2023/9/20*/// spring初始化bean的时候,如果bean实现了InitializingBean接口,
// 会自动调用afterPropertiesSet方法
@Component
public class ConstantUtils implements InitializingBean {@Value("${file.video.videoPath}")String videoPath;@Value("${file.video.chunkSize}")String videoChunkSize;public static String FILE_VIDEO_PATH;public static String FILE_VIDEO_CHUNK_SIZE;public static String CHUNK_PREFIX = "FILE_VIDEO";@Overridepublic void afterPropertiesSet() throws Exception {FILE_VIDEO_PATH = videoPath;FILE_VIDEO_CHUNK_SIZE = videoChunkSize;}
}

RedisHelper

package com.ruoyi.file.utils;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.ListOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;@Component
public class RedisHelper {private static final Logger logger = LoggerFactory.getLogger(RedisHelper.class);public static final int CACHE_TIME_1_YEAR = 60 * 60 * 24 * 365;@Resourceprivate RedisTemplate<Object, Object> redisTemplate;/*** 读取缓存** @param key* @return*/public Object get(final String key) {return redisTemplate.opsForValue().get(key);}/*** 写入缓存*/public boolean set(final String key, Object value) {boolean result = false;try {redisTemplate.opsForValue().set(key, value);result = true;} catch (Exception e) {logger.warn("", e);}return result;}/*** 写入缓存*/public boolean set(final String key, Object value, int seconds) {boolean result = false;try {if (seconds > 0) {redisTemplate.opsForValue().set(key, value, seconds, TimeUnit.SECONDS);} else {redisTemplate.opsForValue().set(key, value);}result = true;} catch (Exception e) {logger.warn("", e);}return result;}public boolean hasKey(String key) {return redisTemplate.hasKey(key);}public boolean exist(final String key) {return redisTemplate.hasKey(key);}/*** 更新缓存*/public boolean getAndSet(final String key, Object value) {boolean result = false;try {redisTemplate.opsForValue().getAndSet(key, value);result = true;} catch (Exception e) {logger.warn("", e);}return result;}/*** 删除缓存*/public boolean delete(final String key) {boolean result = false;try {redisTemplate.delete(key);result = true;} catch (Exception e) {logger.warn("", e);}return result;}/*** 1.Redis设置多个值* 命令:HMSET myhash total 15 success 0 time "2019-12-01 11:10:15"* 2.当一个任务完成之后,把成功的次数加1* 命令:HINCRBY myhash success 1* <p>* 当前有多少个计算(有点过几次计算)* 1.列表中添加值* 命令:RPUSH mylist "hello"* 2.获取列表中所有元素* 命令:LRANGE mylist 0 -1*//*** 设置hash值,同时设置多个属性** @param key 键* @param map 多个属性值用map封装* @return*/public boolean hmset(final String key, Map<String, Object> map) {boolean result = false;try {HashOperations<Object, Object, Object> opsForHash = redisTemplate.opsForHash();opsForHash.putAll(key, map);result = true;} catch (Exception e) {logger.warn("", e);}return result;}/*** 自增值,给hash值某个属性自增** @param key   键* @param field 要自增的属性* @param num   自增值的大小,可以为正数负数* @return*/public boolean hincrby(final String key, String field, Integer num) {boolean result = false;try {HashOperations<Object, Object, Object> opsForHash = redisTemplate.opsForHash();opsForHash.increment(key, field, num);result = true;} catch (Exception e) {logger.warn("", e);}return result;}/*** 自增值,给hash值某个属性自增1** @param key   键* @param field 要自增的属性* @return*/public boolean hincrby(final String key, String field) {boolean result = false;try {HashOperations<Object, Object, Object> opsForHash = redisTemplate.opsForHash();opsForHash.increment(key, field, 1);result = true;} catch (Exception e) {logger.warn("", e);}return result;}/*** 获取hash中的所有数据** @param key* @return*/public Map<Object, Object> hgetall(final String key) {Map<Object, Object> entries = new HashMap<>();try {HashOperations<Object, Object, Object> opsForHash = redisTemplate.opsForHash();entries = opsForHash.entries(key);return entries;} catch (Exception e) {logger.warn("", e);}return entries;}/*** list操作,队列右侧添加值** @param key* @param value* @return*/public boolean rpush(final String key, Object value) {boolean result = false;try {ListOperations<Object, Object> opsForList = redisTemplate.opsForList();opsForList.rightPush(key, value);result = true;} catch (Exception e) {logger.warn("", e);}return result;}/*** 获取列表中的所有元素** @param key* @return*/public List<Object> lrange(final String key) {List<Object> range = new ArrayList<>();try {ListOperations<Object, Object> opsForList = redisTemplate.opsForList();range = opsForList.range(key, 0, -1);return range;} catch (Exception e) {logger.warn("", e);}return range;}/*** 删除list中的值** @param key   list的key* @param value 要删除的list中的value* @return*/public boolean lrem(final String key, Object value) {boolean result = false;try {ListOperations<Object, Object> opsForList = redisTemplate.opsForList();opsForList.remove(key, 0, value);result = true;} catch (Exception e) {logger.warn("", e);}return result;}/*** 设置键的过期时间* @param key 键* @param expiredTimeSecond 过期时间(秒)* @return*/public boolean setKeyExpiredTime(String key, Long expiredTimeSecond){return this.redisTemplate.expire(key, expiredTimeSecond,TimeUnit.SECONDS);}}

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

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

相关文章

量化交易系统开发-实时行情自动化交易-4.4.1.做市策略实现

19年创业做过一年的量化交易但没有成功&#xff0c;作为交易系统的开发人员积累了一些经验&#xff0c;最近想重新研究交易系统&#xff0c;一边整理一边写出来一些思考供大家参考&#xff0c;也希望跟做量化的朋友有更多的交流和合作。 接下来继续说说做市策略实现。 做市策…

webp 网页如何录屏?

工作中正好研究到了一点&#xff1a;记录下这里&#xff1a; 先看下效果&#xff1a; 具体实现代码&#xff1a; &#xfeff; <!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewport&qu…

C#中面试的常见问题005

1、重载和重写 重载&#xff08;Overloading&#xff09; 重载是指在同一个类中定义多个同名方法&#xff0c;但参数列表不同&#xff08;参数的数量、类型或顺序不同&#xff09;。返回类型可以相同也可以不同。重载方法允许你根据传入的参数类型和数量来调用不同的方法。 …

CTF之密码学(BF与Ook)

BrainFuck&#xff08;通常也被称为Brainfuck或BF&#xff09;和Ook是两种非常特殊且有趣的编程语言。以下是对这两种语言的详细介绍&#xff1a; 一、BrainFuck 简介&#xff1a; BrainFuck是一种极小化的计算机语言&#xff0c;由Urban Mller在1993年创建。由于“fuck”在英…

SpringCloud Gateway转发请求到同一个服务的不同端口

SpringCloud Gateway默认不支持将请求路由到一个服务的多个端口 本文将结合Gateway的处理流程&#xff0c;提供一些解决思路 需求背景 公司有一个IM项目&#xff0c;对外暴露了两个端口8081和8082&#xff0c;8081是springboot启动使用的端口&#xff0c;对外提供一些http接口…

MySQL 数据库连接池爆满问题排查与解决

目录 MySQL 数据库连接池爆满问题排查与解决 一、问题影响 二、问题确认 三、收集信息 四、SQL 语句分析 五、应用层代码分析 六、连接池配置检查 七、监控工具使用 八、案例分析 在实际的应用开发中&#xff0c;我们可能会遇到 MySQL 数据库连接池爆满的情况。这种情…

解决发布web接口时数据无法JSON化的问题

解决HTTP接口传输中的JSON序列化问题 引言 当涉及到复杂的数据类型时&#xff0c;如浮点数、Numpy数组、pandas等&#xff0c;直接使用Python的json模块进行序列化可能会遇到问题。本文将解决这些问题&#xff0c;并提供一个通用的方案&#xff0c;确保数据能够顺利地通过HTT…

SlickGrid复选框

分析 1、先在columns首列添加复选框&#xff1b; 2、在SlickGrid注册刚添加的复选框&#xff1b; 3、添加复选框变化事件&#xff1b; 4、注册按钮点击事件&#xff0c;点击获取已选中的行。 展示 代码 复选框样式&#xff08;CSS&#xff09; .slick-cell-checkboxsel {bac…

摄像头原始数据读取——V4L2(userptr模式,V4L2_MEMORY_USERPTR)

摄像头原始数据读取——V4L2(userptr模式,V4L2_MEMORY_USERPTR) 用户指针方式允许用户空间的应用程序分配内存&#xff0c;并将内存地址传递给内核中的驱动程序。驱动程序直接将数据填充到用户空间的内存中&#xff0c;从而避免了数据的拷贝过程。 流程&#xff1a; 通过VIDI…

浏览器缓存与协商缓存

1. 强缓存&#xff08;Strong Cache&#xff09; 定义 强缓存是指在缓存的资源有效期内&#xff0c;浏览器会直接使用缓存中的数据&#xff0c;而不会发起网络请求。也就是说&#xff0c;浏览器会直接从本地缓存读取资源&#xff0c;不会与服务器进行任何交互。 如何控制强缓…

【Python】Uvicorn服务器

【Python】Uvicorn服务器 1.Uvicorn介绍2. Uvicorn 的特点3. Uvicorn 和 FastAPI4. 安装 Uvicorn5. 高级功能6. 性能优化7. 安全与监控8. 部署与维护9. 结论 python官方api地址 1.Uvicorn介绍 Uvicorn 既不是一个传统的“框架”&#xff0c;也不是一个普通的“包”&#xff0…

AI 写作(一):开启创作新纪元(1/10)

一、AI 写作&#xff1a;重塑创作格局 在当今数字化高速发展的时代&#xff0c;AI 写作正以惊人的速度重塑着创作格局。AI 写作在现代社会中占据着举足轻重的地位&#xff0c;发挥着不可替代的作用。 随着信息的爆炸式增长&#xff0c;人们对于内容的需求日益旺盛。AI 写作能够…

RabbitMQ 篇-深入了解延迟消息、MQ 可靠性(生产者可靠性、MQ 可靠性、消费者可靠性)

??博客主页&#xff1a;【_-CSDN博客】** 感谢大家点赞??收藏评论** 文章目录 ???1.0 RabbitMQ 的可靠性 ? ? ? ? 2.0 发送者的可靠性 ? ? ? ? 2.1 生产者重试机制 ? ? ? ? 2.2 生产者确认机制 ? ? ? ? 2.2.1 开启生产者确认机制 ? ? ? ? 2.2…

C# 创建快捷方式文件和硬链接文件

C# 创建快捷方式文件和硬链接文件 引言什么是快捷方式什么是硬链接文件硬链接与快捷方式不同 实现创建快捷方式文件实现创建硬链接文件小结 引言 什么是快捷方式 平常我们最常window桌面上点击的左下角带小箭头的文件就是快捷方式了&#xff0c;大家都很熟悉它。快捷方式是Wi…

问:SpringBoot核心配置文件都有啥,怎么配?

在SpringBoot的开发过程中&#xff0c;核心配置文件扮演着至关重要的角色。这些文件用于配置应用程序的各种属性和环境设置&#xff0c;使得开发者能够灵活地定制和管理应用程序的行为。本文将探讨SpringBoot的核心配置文件&#xff0c;包括它们的作用、区别&#xff0c;并通过…

【机器学习】数据集合集!

本文将为您介绍经典、热门的数据集&#xff0c;希望对您在选择适合的数据集时有所帮助。 1 privacy 更新时间&#xff1a;2024-11-26 访问地址: GitHub 描述&#xff1a; 此存储库包含 TensorFlow Privacy&#xff08;一种 Python&#xff09;的源代码 库&#xff0c;其中包…

Linux V4L2框架介绍

linux V4L2框架介绍 V4L2框架介绍 V4L2&#xff0c;全称Video for Linux 2&#xff0c;是Linux操作系统下用于视频数据采集设备的驱动框。它提供了一种标准化的方式使用户空间程序能够与视频设备进行通信和交互。通过V4L2接口&#xff0c;用户可以方便地实现视频图像数据的采…

[网安靶场] [更新中] UPLOAD LABS —— 靶场笔记合集

GitHub - c0ny1/upload-labs: 一个想帮你总结所有类型的上传漏洞的靶场一个想帮你总结所有类型的上传漏洞的靶场. Contribute to c0ny1/upload-labs development by creating an account on GitHub.https://github.com/c0ny1/upload-labs 0x01&#xff1a;UPLOAD LABS 靶场初识…

SpringBoot社团管理:用户体验优化

3系统分析 3.1可行性分析 通过对本社团管理系统实行的目的初步调查和分析&#xff0c;提出可行性方案并对其一一进行论证。我们在这里主要从技术可行性、经济可行性、操作可行性等方面进行分析。 3.1.1技术可行性 本社团管理系统采用SSM框架&#xff0c;JAVA作为开发语言&#…

uniapp内嵌的webview H5与应用通信

H5端&#xff1a; 1、找到index.html引入依赖 <script type"text/javascript" src"https://unpkg.com/dcloudio/uni-webview-js0.0.3/index.js"></script> 2、在需要通讯处发送消息 uni.postMessage({data:{code:200,msg:"处理完成&q…