java大视频分片上传

打印 上一主题 下一主题

主题 825|帖子 825|积分 2475

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

  1. @ApiOperation(value = "上传视频", notes = "上传视频", httpMethod = "POST", response = WebResult.class)
  2. @PostMapping(value = "/uploadVideo", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)//
  3. public AjaxResult uploadVideo(@RequestParam(name = "file") MultipartFile file,
  4.                               @RequestParam(name = "chunkIndex") Integer chunkIndex,
  5.                               @RequestParam(name = "md5") String md5,
  6.                               @RequestParam(name = "totalFileSize") Long totalFileSize,
  7.                               @RequestParam(name = "fileName") String fileName,
  8.                               @RequestParam(name = "userName") String userName,
  9.                               HttpServletRequest request) throws Exception {
  10.     if (null == file || file.isEmpty()) {
  11.         return AjaxResult.error("文件内容不能为空!");
  12.     }
  13.     return fileSystemService.uploadVideo(file, chunkIndex, md5, fileName, userName);
  14.     }
复制代码
service

  1. public AjaxResult uploadVideo(MultipartFile file, Integer chunkIndex, String md5, String fileName, String userName) throws IOException {
  2.         //创建存放文件夹
  3.         String date = DateTime.now().toString("yyyyMMdd");
  4.         String dirPath = ConstantUtils.FILE_VIDEO_PATH + userName + "/" + date + "/" + md5 + "/";
  5.         File dirFile = new File(dirPath);
  6.         if (!dirFile.exists()){
  7.             dirFile.mkdirs();
  8.         }
  9.         //分区文件
  10.         String relativeFilePath = dirPath + fileName;
  11.         File tempFile = new File(relativeFilePath);
  12.         RandomAccessFile rw = new RandomAccessFile(tempFile, "rw");
  13.         //定位到分片的偏移量
  14.         rw.seek(Long.parseLong(ConstantUtils.FILE_VIDEO_CHUNK_SIZE) * chunkIndex);
  15.         //写入分片数据
  16.         rw.write(file.getBytes());
  17.         //关闭流
  18.         rw.close();
  19.         //读取已经分片的集合
  20.         Set<Object> hasChunkList = new HashSet<>();
  21.         String hasChunkKey = ConstantUtils.CHUNK_PREFIX + md5;
  22.         if (redisHelper.hasKey(hasChunkKey)){
  23.             Object o = redisHelper.get(hasChunkKey);
  24.             JSONArray array = JSONUtil.parseArray(o);
  25.             hasChunkList.addAll(array);
  26.         }
  27.         hasChunkList.add(chunkIndex);
  28.         //最新分片下标跟新到redis
  29.         redisHelper.set(hasChunkKey,hasChunkList);
  30.         HashMap<String, Object> map = new HashMap<>();
  31.         map.put("url",userName + "/" + date + "/" + md5 + "/" + fileName);
  32.         map.put("hasList",hasChunkList);
  33.         return AjaxResult.success(map);
  34.     }
复制代码
ConstantUtils

  1. package com.ruoyi.file.utils;
  2. import org.springframework.beans.factory.InitializingBean;
  3. import org.springframework.beans.factory.annotation.Value;
  4. import org.springframework.stereotype.Component;
  5. /**
  6. * @author csb
  7. * @description: 获取配置文件常量数据
  8. * @date 2023/9/20
  9. */
  10. // spring初始化bean的时候,如果bean实现了InitializingBean接口,
  11. // 会自动调用afterPropertiesSet方法
  12. @Component
  13. public class ConstantUtils implements InitializingBean {
  14.     @Value("${file.video.videoPath}")
  15.     String videoPath;
  16.     @Value("${file.video.chunkSize}")
  17.     String videoChunkSize;
  18.     public static String FILE_VIDEO_PATH;
  19.     public static String FILE_VIDEO_CHUNK_SIZE;
  20.     public static String CHUNK_PREFIX = "FILE_VIDEO";
  21.     @Override
  22.     public void afterPropertiesSet() throws Exception {
  23.         FILE_VIDEO_PATH = videoPath;
  24.         FILE_VIDEO_CHUNK_SIZE = videoChunkSize;
  25.     }
  26. }
复制代码
RedisHelper

  1. package com.ruoyi.file.utils;
  2. import org.slf4j.Logger;
  3. import org.slf4j.LoggerFactory;
  4. import org.springframework.data.redis.core.HashOperations;
  5. import org.springframework.data.redis.core.ListOperations;
  6. import org.springframework.data.redis.core.RedisTemplate;
  7. import org.springframework.stereotype.Component;
  8. import javax.annotation.Resource;
  9. import java.util.ArrayList;
  10. import java.util.HashMap;
  11. import java.util.List;
  12. import java.util.Map;
  13. import java.util.concurrent.TimeUnit;
  14. @Component
  15. public class RedisHelper {
  16.     private static final Logger logger = LoggerFactory.getLogger(RedisHelper.class);
  17.     public static final int CACHE_TIME_1_YEAR = 60 * 60 * 24 * 365;
  18.     @Resource
  19.     private RedisTemplate<Object, Object> redisTemplate;
  20.     /**
  21.      * 读取缓存
  22.      *
  23.      * @param key
  24.      * @return
  25.      */
  26.     public Object get(final String key) {
  27.         return redisTemplate.opsForValue().get(key);
  28.     }
  29.     /**
  30.      * 写入缓存
  31.      */
  32.     public boolean set(final String key, Object value) {
  33.         boolean result = false;
  34.         try {
  35.             redisTemplate.opsForValue().set(key, value);
  36.             result = true;
  37.         } catch (Exception e) {
  38.             logger.warn("", e);
  39.         }
  40.         return result;
  41.     }
  42.     /**
  43.      * 写入缓存
  44.      */
  45.     public boolean set(final String key, Object value, int seconds) {
  46.         boolean result = false;
  47.         try {
  48.             if (seconds > 0) {
  49.                 redisTemplate.opsForValue().set(key, value, seconds, TimeUnit.SECONDS);
  50.             } else {
  51.                 redisTemplate.opsForValue().set(key, value);
  52.             }
  53.             result = true;
  54.         } catch (Exception e) {
  55.             logger.warn("", e);
  56.         }
  57.         return result;
  58.     }
  59.     public boolean hasKey(String key) {
  60.         return redisTemplate.hasKey(key);
  61.     }
  62.     public boolean exist(final String key) {
  63.         return redisTemplate.hasKey(key);
  64.     }
  65.     /**
  66.      * 更新缓存
  67.      */
  68.     public boolean getAndSet(final String key, Object value) {
  69.         boolean result = false;
  70.         try {
  71.             redisTemplate.opsForValue().getAndSet(key, value);
  72.             result = true;
  73.         } catch (Exception e) {
  74.             logger.warn("", e);
  75.         }
  76.         return result;
  77.     }
  78.     /**
  79.      * 删除缓存
  80.      */
  81.     public boolean delete(final String key) {
  82.         boolean result = false;
  83.         try {
  84.             redisTemplate.delete(key);
  85.             result = true;
  86.         } catch (Exception e) {
  87.             logger.warn("", e);
  88.         }
  89.         return result;
  90.     }
  91.     /**
  92.      * 1.Redis设置多个值
  93.      * 命令:HMSET myhash total 15 success 0 time "2019-12-01 11:10:15"
  94.      * 2.当一个任务完成之后,把成功的次数加1
  95.      * 命令:HINCRBY myhash success 1
  96.      * <p>
  97.      * 当前有多少个计算(有点过几次计算)
  98.      * 1.列表中添加值
  99.      * 命令:RPUSH mylist "hello"
  100.      * 2.获取列表中所有元素
  101.      * 命令:LRANGE mylist 0 -1
  102.      */
  103.     /**
  104.      * 设置hash值,同时设置多个属性
  105.      *
  106.      * @param key 键
  107.      * @param map 多个属性值用map封装
  108.      * @return
  109.      */
  110.     public boolean hmset(final String key, Map<String, Object> map) {
  111.         boolean result = false;
  112.         try {
  113.             HashOperations<Object, Object, Object> opsForHash = redisTemplate.opsForHash();
  114.             opsForHash.putAll(key, map);
  115.             result = true;
  116.         } catch (Exception e) {
  117.             logger.warn("", e);
  118.         }
  119.         return result;
  120.     }
  121.     /**
  122.      * 自增值,给hash值某个属性自增
  123.      *
  124.      * @param key   键
  125.      * @param field 要自增的属性
  126.      * @param num   自增值的大小,可以为正数负数
  127.      * @return
  128.      */
  129.     public boolean hincrby(final String key, String field, Integer num) {
  130.         boolean result = false;
  131.         try {
  132.             HashOperations<Object, Object, Object> opsForHash = redisTemplate.opsForHash();
  133.             opsForHash.increment(key, field, num);
  134.             result = true;
  135.         } catch (Exception e) {
  136.             logger.warn("", e);
  137.         }
  138.         return result;
  139.     }
  140.     /**
  141.      * 自增值,给hash值某个属性自增1
  142.      *
  143.      * @param key   键
  144.      * @param field 要自增的属性
  145.      * @return
  146.      */
  147.     public boolean hincrby(final String key, String field) {
  148.         boolean result = false;
  149.         try {
  150.             HashOperations<Object, Object, Object> opsForHash = redisTemplate.opsForHash();
  151.             opsForHash.increment(key, field, 1);
  152.             result = true;
  153.         } catch (Exception e) {
  154.             logger.warn("", e);
  155.         }
  156.         return result;
  157.     }
  158.     /**
  159.      * 获取hash中的所有数据
  160.      *
  161.      * @param key
  162.      * @return
  163.      */
  164.     public Map<Object, Object> hgetall(final String key) {
  165.         Map<Object, Object> entries = new HashMap<>();
  166.         try {
  167.             HashOperations<Object, Object, Object> opsForHash = redisTemplate.opsForHash();
  168.             entries = opsForHash.entries(key);
  169.             return entries;
  170.         } catch (Exception e) {
  171.             logger.warn("", e);
  172.         }
  173.         return entries;
  174.     }
  175.     /**
  176.      * list操作,队列右侧添加值
  177.      *
  178.      * @param key
  179.      * @param value
  180.      * @return
  181.      */
  182.     public boolean rpush(final String key, Object value) {
  183.         boolean result = false;
  184.         try {
  185.             ListOperations<Object, Object> opsForList = redisTemplate.opsForList();
  186.             opsForList.rightPush(key, value);
  187.             result = true;
  188.         } catch (Exception e) {
  189.             logger.warn("", e);
  190.         }
  191.         return result;
  192.     }
  193.     /**
  194.      * 获取列表中的所有元素
  195.      *
  196.      * @param key
  197.      * @return
  198.      */
  199.     public List<Object> lrange(final String key) {
  200.         List<Object> range = new ArrayList<>();
  201.         try {
  202.             ListOperations<Object, Object> opsForList = redisTemplate.opsForList();
  203.             range = opsForList.range(key, 0, -1);
  204.             return range;
  205.         } catch (Exception e) {
  206.             logger.warn("", e);
  207.         }
  208.         return range;
  209.     }
  210.     /**
  211.      * 删除list中的值
  212.      *
  213.      * @param key   list的key
  214.      * @param value 要删除的list中的value
  215.      * @return
  216.      */
  217.     public boolean lrem(final String key, Object value) {
  218.         boolean result = false;
  219.         try {
  220.             ListOperations<Object, Object> opsForList = redisTemplate.opsForList();
  221.             opsForList.remove(key, 0, value);
  222.             result = true;
  223.         } catch (Exception e) {
  224.             logger.warn("", e);
  225.         }
  226.         return result;
  227.     }
  228.     /**
  229.      * 设置键的过期时间
  230.      * @param key 键
  231.      * @param expiredTimeSecond 过期时间(秒)
  232.      * @return
  233.      */
  234.     public boolean setKeyExpiredTime(String key, Long expiredTimeSecond){
  235.         return this.redisTemplate.expire(key, expiredTimeSecond,TimeUnit.SECONDS);
  236.     }
  237. }
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

干翻全岛蛙蛙

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表