实现原理,前端控制每次上传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);
- //最新分片下标跟新到redis
- redisHelper.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";
- @Override
- public 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;
- @Resource
- private 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);
- }
- }
复制代码 免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |