当前位置:   article > 正文

FastDFS结合vue-simple-uploader实现断点续传_appendfilestorageclient

appendfilestorageclient

参考:https://gitee.com/zwlan/renewFastdfs

1. maven依赖

  1. <!--<fast.clent.version>1.26.2</fast.clent.version>-->
  2. <!--<hutool.all.version>4.0.12</hutool.all.version>-->
  1. <dependency>
  2. <groupId>cn.hutool</groupId>
  3. <artifactId>hutool-all</artifactId>
  4. <version>${hutool.all.version}</version>
  5. </dependency>
  6. <dependency>
  7. <groupId>com.github.tobato</groupId>
  8. <artifactId>fastdfs-client</artifactId>
  9. <version>${fast.clent.version}</version>
  10. </dependency>

2. 部分配置

#redis

spring:  
  redis:
    open: true  # 是否开启redis缓存  true开启   false关闭
    database: 0
    host: xx.xx.xx.xx # ip
    port: xxxx # port
    password:   # 密码(默认为空)
    timeout: 6000ms  # 连接超时时长(毫秒)
    jedis:
      pool:
        max-active: 1000  # 连接池最大连接数(使用负值表示没有限制)
        max-wait: -1ms      # 连接池最大阻塞等待时间(使用负值表示没有限制)
        max-idle: 10      # 连接池中的最大空闲连接
        min-idle: 5       # 连接池中的最小空闲连接

  1. #FastDFS Client
  2. fdfs:
  3. so-timeout: 1501
  4. connect-timeout: 601
  5. thumb-image: #缩略图生成参数
  6. width: 150
  7. height: 150
  8. tracker-list: #TrackerList参数,支持多个
  9. - xx.xx.xx.xx:22122 #ip:port
  10. pool:
  11. max-total: 153
  12. jmx-name-base: 1
  13. jmx-name-prefix: 1

# nginx 反向代理之后的查看资源路径
fastDFS:
  file:
    server:
      url: http://xx.xx.xx.xx:8091 # ip:port
    show:
      url: http://xx.xx.xx.xx:8090 

#FastDFS临时上传路径
file:
  upload:
    temp:
      path: /data0/fastdfs/temp

3. 代码

  1. package cn.longrace.wisdom.modules.uploader.controller;
  2. import cn.hutool.core.io.FileUtil;
  3. import cn.longrace.wisdom.common.utils.RedisUtils;
  4. import cn.longrace.wisdom.common.vo.R;
  5. import cn.longrace.wisdom.modules.sys.controller.AbstractController;
  6. import cn.longrace.wisdom.modules.uploader.common.UpLoadConstant;
  7. import cn.longrace.wisdom.modules.uploader.entity.Chunk;
  8. import cn.longrace.wisdom.modules.uploader.entity.FileInfo;
  9. import cn.longrace.wisdom.modules.uploader.service.ChunkService;
  10. import cn.longrace.wisdom.modules.uploader.service.FileInfoService;
  11. import cn.longrace.wisdom.modules.uploader.util.FileUtils;
  12. import com.github.tobato.fastdfs.domain.StorePath;
  13. import com.github.tobato.fastdfs.service.AppendFileStorageClient;
  14. import lombok.extern.slf4j.Slf4j;
  15. import org.springframework.beans.factory.annotation.Autowired;
  16. import org.springframework.beans.factory.annotation.Value;
  17. import org.springframework.util.StringUtils;
  18. import org.springframework.web.bind.annotation.GetMapping;
  19. import org.springframework.web.bind.annotation.PostMapping;
  20. import org.springframework.web.bind.annotation.RequestMapping;
  21. import org.springframework.web.bind.annotation.RestController;
  22. import org.springframework.web.multipart.MultipartFile;
  23. import javax.annotation.Resource;
  24. import javax.servlet.http.HttpServletResponse;
  25. import java.io.File;
  26. import java.io.FileInputStream;
  27. import java.nio.file.Files;
  28. import java.nio.file.Path;
  29. import java.nio.file.Paths;
  30. import java.util.Random;
  31. import static cn.longrace.wisdom.modules.uploader.util.FileUtils.generatePath;
  32. /**
  33. * @author
  34. * @date
  35. */
  36. @RestController
  37. @RequestMapping("/new/uploader")
  38. @Slf4j
  39. public class NewUploadController extends AbstractController {
  40. @Value("${fastDFS.file.server.url}")
  41. private String fileUploadUrl;
  42. @Value("${fastDFS.file.show.url}")
  43. private String showFileUploadUrl;
  44. @Value("${file.upload.temp.path}")
  45. private String uploadFolder;
  46. @Autowired
  47. private AppendFileStorageClient appendFileStorageClient;
  48. private Long curriculumId;
  49. @Resource
  50. private ChunkService chunkService;
  51. @Autowired
  52. RedisUtils redisUtils;
  53. @Autowired
  54. FileInfoService fileInfoService;
  55. /**
  56. * 方式一:
  57. * 功能描述:上传文件
  58. *
  59. * @param:
  60. * @return:
  61. * @auther:
  62. * @date:
  63. */
  64. @PostMapping("/chunk")
  65. public String uploadChunk(Chunk chunk) {
  66. MultipartFile file = chunk.getFile();
  67. log.debug("file originName: {}, chunkNumber: {}", file.getOriginalFilename(), chunk.getChunkNumber());
  68. try {
  69. String contentType = file.getContentType();
  70. chunk.setType(contentType);
  71. byte[] bytes = file.getBytes();
  72. Path p1 = Paths.get(generatePath(uploadFolder, chunk));
  73. //文件写入指定路径
  74. Path p = Files.write(p1, bytes);
  75. log.debug("文件 {} 写入成功, uuid:{}", chunk.getFilename(), chunk.getIdentifier());
  76. StorePath path = null;
  77. try {
  78. File f = p.toFile();
  79. if (redisUtils.get(chunk.getIdentifier()) == null) {
  80. // 创建可续传的文件
  81. path = appendFileStorageClient.uploadAppenderFile(UpLoadConstant.DEFAULT_GROUP, new FileInputStream(f), f.length(), FileUtil.extName(chunk.getFilename()));
  82. redisUtils.set(chunk.getIdentifier(), path.getPath());
  83. } else {
  84. // 最后一个参数记录文件的偏移量
  85. appendFileStorageClient.modifyFile(UpLoadConstant.DEFAULT_GROUP, redisUtils.get(chunk.getIdentifier()), new FileInputStream(f), f.length(),(chunk.getChunkNumber() -1)*(10*1024*1024));
  86. }
  87. } catch (Exception e) {
  88. e.printStackTrace();
  89. }
  90. // 保存chunk
  91. Random rn = new Random(1000);
  92. chunk.setId(rn.nextLong());
  93. chunk.setCreator(this.getUserId());
  94. chunk.setCurriculumId(curriculumId);
  95. chunkService.saveChunk(chunk);
  96. return "文件上传成功";
  97. }catch (Exception e) {
  98. e.printStackTrace();
  99. return "后端异常...";
  100. }
  101. }
  102. @GetMapping("/chunk")
  103. public Object checkChunk(Chunk chunk, HttpServletResponse response) {
  104. curriculumId = chunk.getCurriculumId();
  105. if (chunkService.checkChunk(chunk)) {
  106. response.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
  107. }
  108. return chunk;
  109. }
  110. @PostMapping("/mergeFile")
  111. public R test (FileInfo fileInfo) throws Exception {
  112. // TODO 截图一----------------------
  113. String filePath = showFileUploadUrl + "/"+ UpLoadConstant.DEFAULT_GROUP + "/" + redisUtils.get(fileInfo.getIdentifier());
  114. String filename = fileInfo.getFileName();
  115. String extension = filename.substring(filename.indexOf('.') + 1, filename.length());
  116. String finalExtension = "mp4";
  117. try {
  118. if (!StringUtils.isEmpty(extension) && extension.equals(finalExtension)) {
  119. System.out.println("==============视频截图开始================");
  120. String imgFileName = filename + ".jpg";
  121. String imgFilePath = uploadFolder + "/" + filename + ".jpg";
  122. FileUtils.fetchFrame(filePath, imgFilePath);
  123. File tempImgFile = new File(imgFilePath);
  124. // FileInputStream fileImgInputStream = new FileInputStream(tempImgFile);
  125. // MultipartFile multipartImgFile = new MockMultipartFile(imgFileName, imgFileName,
  126. // ContentType.APPLICATION_OCTET_STREAM.toString(), fileImgInputStream);
  127. //
  128. // String jsonImgStr = HttpUtils.upload(fileUploadUrl, multipartImgFile);
  129. // System.out.println("jsonImgStr-------------------------"+jsonImgStr);
  130. StorePath path = appendFileStorageClient.uploadAppenderFile(UpLoadConstant.DEFAULT_GROUP, new FileInputStream(tempImgFile), tempImgFile.length(), FileUtil.extName(imgFileName));
  131. fileInfo.setImgLocation(UpLoadConstant.DEFAULT_GROUP + "/" + path.getPath());
  132. tempImgFile.delete();
  133. }
  134. } catch (Exception e) {
  135. throw new RuntimeException(e);
  136. }
  137. System.out.println("==============视频截图结束================");
  138.   // UpLoadConstant.DEFAULT_GROUP 即group1
  139. fileInfo.setLocation(UpLoadConstant.DEFAULT_GROUP + "/" + redisUtils.get(fileInfo.getIdentifier()));
  140. this.fileInfoService.insert(fileInfo);
  141. // 删除redis中文件key
  142. redisUtils.delete(fileInfo.getIdentifier());
  143. // 删除临时文件目录
  144. FileUtils.deleteDir(new File(uploadFolder + "/" + fileInfo.getIdentifier()));
  145. return R.ok().put("fileInfo",fileInfo);
  146. }
  147. }

4. 相关实体类

  1. package cn.longrace.wisdom.modules.uploader.entity;
  2. import com.baomidou.mybatisplus.annotations.TableField;
  3. import com.baomidou.mybatisplus.annotations.TableName;
  4. import lombok.Data;
  5. import org.springframework.web.multipart.MultipartFile;
  6. import java.io.Serializable;
  7. /**
  8. * 文件分块大小
  9. */
  10. @Data
  11. @TableName("lr_teacher_resource_chunk")
  12. public class Chunk implements Serializable {
  13. private Long id;
  14. /**
  15. * 当前文件块,从1开始
  16. */
  17. private Integer chunkNumber;
  18. /**
  19. * 分块大小
  20. */
  21. private Long chunkSize;
  22. /**
  23. * 当前分块大小
  24. */
  25. private Long currentChunkSize;
  26. /**
  27. * 总大小
  28. */
  29. private Long totalSize;
  30. /**
  31. * 文件标识
  32. */
  33. private String identifier;
  34. /**
  35. * 文件名
  36. */
  37. private String filename;
  38. /**
  39. * 相对路径
  40. */
  41. private String relativePath;
  42. /**
  43. * 总块数
  44. */
  45. private Integer totalChunks;
  46. /**
  47. * 文件类型
  48. */
  49. private String type;
  50. /**
  51. * 课程ID
  52. */
  53. private Long curriculumId;
  54. /**
  55. * 创建人
  56. */
  57. private Long creator;
  58. /**
  59. * 所属备课ID
  60. */
  61. private Long prepareId;
  62. /**
  63. * 所属班级ID
  64. */
  65. private Long classId;
  66. @TableField(exist = false)
  67. private MultipartFile file;
  68. }
  1. package cn.longrace.wisdom.modules.uploader.entity;
  2. import com.baomidou.mybatisplus.annotations.TableName;
  3. import lombok.Data;
  4. import java.io.Serializable;
  5. /**
  6. * 文件信息实体类
  7. */
  8. @Data
  9. @TableName("lr_teacher_resource_file_info")
  10. public class FileInfo implements Serializable {
  11. private Long id;
  12. /**
  13. * 文件名称
  14. */
  15. private String fileName;
  16. /**
  17. * 文件标识
  18. */
  19. private String identifier;
  20. /**
  21. * 文件总大小
  22. */
  23. private Long totalSize;
  24. /**
  25. * 文件类型
  26. */
  27. private String type;
  28. /**
  29. * 文件路径
  30. */
  31. private String location;
  32. /**
  33. * 视频文件封面路径
  34. */
  35. private String imgLocation;
  36. }
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/170143
推荐阅读
相关标签
  

闽ICP备14008679号