断点续传功能完善

This commit is contained in:
马超 2021-08-17 18:27:33 +08:00
parent f74ff38c94
commit 0b69d4bbd2
26 changed files with 320 additions and 91 deletions

View File

@ -2,8 +2,8 @@ package com.qiwenshare.file.api;
import com.qiwenshare.file.domain.FileBean;
import com.qiwenshare.file.domain.StorageBean;
import com.qiwenshare.file.dto.DownloadFileDTO;
import com.qiwenshare.file.dto.UploadFileDTO;
import com.qiwenshare.file.dto.file.DownloadFileDTO;
import com.qiwenshare.file.dto.file.UploadFileDTO;
import com.qiwenshare.file.dto.file.PreviewDTO;
import javax.servlet.http.HttpServletRequest;

View File

@ -0,0 +1,10 @@
package com.qiwenshare.file.api;
import com.baomidou.mybatisplus.extension.service.IService;
import com.qiwenshare.file.domain.UploadTaskDetail;
import java.util.List;
public interface IUploadTaskDetailService extends IService<UploadTaskDetail> {
List<Integer> getUploadedChunkNumList(String identifier);
}

View File

@ -0,0 +1,11 @@
package com.qiwenshare.file.api;
import com.baomidou.mybatisplus.extension.service.IService;
import com.qiwenshare.file.domain.UploadTask;
import com.qiwenshare.file.domain.UploadTaskDetail;
import java.util.List;
public interface IUploadTaskService extends IService<UploadTask> {
}

View File

@ -16,12 +16,11 @@ import com.qiwenshare.file.config.es.FileSearch;
import com.qiwenshare.file.domain.TreeNode;
import com.qiwenshare.file.domain.UserBean;
import com.qiwenshare.file.domain.UserFile;
import com.qiwenshare.file.dto.BatchMoveFileDTO;
import com.qiwenshare.file.dto.CopyFileDTO;
import com.qiwenshare.file.dto.MoveFileDTO;
import com.qiwenshare.file.dto.file.BatchMoveFileDTO;
import com.qiwenshare.file.dto.file.CopyFileDTO;
import com.qiwenshare.file.dto.file.MoveFileDTO;
import com.qiwenshare.file.dto.file.*;
import com.qiwenshare.file.vo.file.FileListVo;
import com.qiwenshare.ufop.factory.UFOPFactory;
import com.qiwenshare.ufop.util.UFOPUtils;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
@ -32,7 +31,6 @@ import org.eclipse.jetty.util.StringUtil;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
@ -42,8 +40,6 @@ import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
@Tag(name = "file", description = "该接口为文件接口,主要用来做一些文件的基本操作,如创建目录,删除,移动,复制等。")
@RestController
@ -51,24 +47,18 @@ import java.util.concurrent.Executors;
@RequestMapping("/file")
public class FileController {
@Value("${ufop.storage-type}")
private Integer storageType;
@Resource
IFileService fileService;
@Resource
IUserService userService;
@Resource
IUserFileService userFileService;
@Resource
UFOPFactory ufopFactory;
@Autowired
private ElasticsearchRestTemplate elasticsearchRestTemplate;
@Resource
FileDealComp fileDealComp;
public static Executor executor = Executors.newFixedThreadPool(20);
public static final String CURRENT_MODULE = "文件接口";
@ -291,11 +281,13 @@ public class FileController {
if (sessionUserBean == null) {
throw new NotLoginException();
}
String oldfilePath = copyFileDTO.getOldFilePath();
long userFileId = copyFileDTO.getUserFileId();
UserFile userFile = userFileService.getById(userFileId);
String oldfilePath = userFile.getFilePath();
String newfilePath = copyFileDTO.getFilePath();
String fileName = copyFileDTO.getFileName();
String extendName = copyFileDTO.getExtendName();
if (StringUtil.isEmpty(extendName)) {
String fileName = userFile.getFileName();
String extendName = userFile.getExtendName();
if (userFile.getIsDir() == 1) {
String testFilePath = oldfilePath + fileName + "/";
if (newfilePath.startsWith(testFilePath)) {
return RestResult.fail().message("原路径与目标路径冲突,不能移动");

View File

@ -1,25 +1,21 @@
package com.qiwenshare.file.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.qiwenshare.common.anno.MyLog;
import com.qiwenshare.common.exception.NotLoginException;
import com.qiwenshare.common.result.RestResult;
import com.qiwenshare.common.util.DateUtil;
import com.qiwenshare.common.util.MimeUtils;
import com.qiwenshare.file.api.IFileService;
import com.qiwenshare.file.api.IFiletransferService;
import com.qiwenshare.file.api.IUserFileService;
import com.qiwenshare.file.api.IUserService;
import com.qiwenshare.file.api.*;
import com.qiwenshare.file.component.FileDealComp;
import com.qiwenshare.file.domain.FileBean;
import com.qiwenshare.file.domain.StorageBean;
import com.qiwenshare.file.domain.UserBean;
import com.qiwenshare.file.domain.UserFile;
import com.qiwenshare.file.dto.DownloadFileDTO;
import com.qiwenshare.file.dto.UploadFileDTO;
import com.qiwenshare.file.domain.*;
import com.qiwenshare.file.dto.file.DownloadFileDTO;
import com.qiwenshare.file.dto.file.UploadFileDTO;
import com.qiwenshare.file.dto.file.PreviewDTO;
import com.qiwenshare.file.service.StorageService;
import com.qiwenshare.file.vo.file.FileListVo;
import com.qiwenshare.file.vo.file.UploadFileVo;
import com.qiwenshare.ufop.constant.UploadFileStatusEnum;
import com.qiwenshare.ufop.util.UFOPUtils;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
@ -54,6 +50,11 @@ public class FiletransferController {
FileDealComp fileDealComp;
@Resource
StorageService storageService;
@Resource
IUploadTaskService uploadTaskService;
@Resource
IUploadTaskDetailService uploadTaskDetailService;
public static final String CURRENT_MODULE = "文件传输接口";
@ -112,6 +113,33 @@ public class FiletransferController {
} else {
uploadFileVo.setSkipUpload(false);
List<Integer> uploaded = uploadTaskDetailService.getUploadedChunkNumList(uploadFileDto.getIdentifier());
if (uploaded != null && !uploaded.isEmpty()) {
uploadFileVo.setUploaded(uploaded);
} else {
LambdaQueryWrapper<UploadTask> lambdaQueryWrapper = new LambdaQueryWrapper<>();
lambdaQueryWrapper.eq(UploadTask::getIdentifier, uploadFileDto.getIdentifier());
List<UploadTask> rslist = uploadTaskService.list(lambdaQueryWrapper);
if (rslist == null || rslist.isEmpty()) {
UploadTask uploadTask = new UploadTask();
uploadTask.setIdentifier(uploadFileDto.getIdentifier());
uploadTask.setUploadTime(DateUtil.getCurrentTime());
uploadTask.setUploadStatus(UploadFileStatusEnum.UNCOMPLATE.getCode());
uploadTask.setFileName(uploadFileDto.getFilename());
String relativePath = uploadFileDto.getRelativePath();
if (relativePath.contains("/")) {
uploadTask.setFilePath(uploadFileDto.getFilePath() + UFOPUtils.getParentPath(relativePath) + "/");
} else {
uploadTask.setFilePath(uploadFileDto.getFilePath());
}
uploadTask.setExtendName(uploadTask.getExtendName());
uploadTask.setUserId(sessionUserBean.getUserId());
uploadTaskService.save(uploadTask);
}
}
}
return RestResult.success().data(uploadFileVo);

View File

@ -1,11 +1,8 @@
package com.qiwenshare.file.controller;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.qiwenshare.common.anno.MyLog;
import com.qiwenshare.common.exception.NotLoginException;
import com.qiwenshare.common.util.DateUtil;
import com.qiwenshare.common.result.RestResult;
import com.qiwenshare.file.api.IRecoveryFileService;
import com.qiwenshare.file.api.IUserFileService;
@ -13,8 +10,8 @@ import com.qiwenshare.file.api.IUserService;
import com.qiwenshare.file.domain.RecoveryFile;
import com.qiwenshare.file.domain.UserBean;
import com.qiwenshare.file.domain.UserFile;
import com.qiwenshare.file.dto.BatchDeleteRecoveryFileDTO;
import com.qiwenshare.file.dto.DeleteRecoveryFileDTO;
import com.qiwenshare.file.dto.file.DeleteRecoveryFileDTO;
import com.qiwenshare.file.dto.recoveryfile.BatchDeleteRecoveryFileDTO;
import com.qiwenshare.file.dto.recoveryfile.RestoreFileDTO;
import com.qiwenshare.file.vo.file.RecoveryFileListVo;
import io.swagger.v3.oas.annotations.Operation;

View File

@ -0,0 +1,42 @@
package com.qiwenshare.file.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import javax.persistence.*;
@Data
@Table(name = "uploadtask")
@Entity
@TableName("uploadtask")
public class UploadTask {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@TableId(type = IdType.AUTO)
@Column(columnDefinition = "bigint(20)")
private Long uploadTaskId;
@Column(columnDefinition = "bigint(20)")
private Long userId;
@Column(columnDefinition="varchar(32)")
private String identifier;
@Column(columnDefinition="varchar(100)")
private String fileName;
@Column(columnDefinition="varchar(500)")
private String filePath;
@Column(columnDefinition="varchar(100)")
private String extendName;
@Column(columnDefinition="varchar(25)")
private String uploadTime;
@Column(columnDefinition="int(1)")
private int uploadStatus;
}

View File

@ -0,0 +1,42 @@
package com.qiwenshare.file.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import javax.persistence.*;
@Data
@Table(name = "uploadtaskdetail")
@Entity
@TableName("uploadtaskdetail")
public class UploadTaskDetail {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@TableId(type = IdType.AUTO)
@Column(columnDefinition="bigint(20)")
private Long uploadTaskDetailId;
@Column(columnDefinition="varchar(500)")
private String filePath;
@Column(columnDefinition="varchar(100)")
private String filename;
@Column(columnDefinition="int(5)")
private int chunkNumber;
@Column(columnDefinition="bigint(10)")
private Integer chunkSize;
@Column(columnDefinition="varchar(500)")
private String relativePath;
@Column(columnDefinition="int(5)")
private Integer totalChunks;
@Column(columnDefinition="bigint(10)")
private Integer totalSize;
@Column(columnDefinition="varchar(32)")
private String identifier;
}

View File

@ -1,12 +0,0 @@
package com.qiwenshare.file.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Data
@Schema(name = "批量删除回收文件DTO",required = true)
public class BatchDeleteRecoveryFileDTO {
@Schema(description = "回收用户文件id")
private String recoveryFileIds;
}

View File

@ -1,26 +0,0 @@
package com.qiwenshare.file.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Data
@Schema(name = "复制文件DTO",required = true)
public class CopyFileDTO {
@Schema(description = "用户文件id", required = true)
private long userFileId;
@Schema(description = "文件路径", required = true)
private String filePath;
@Schema(description = "文件名", required = true)
@Deprecated
private String fileName;
@Schema(description = "旧文件名", required = true)
@Deprecated
private String oldFilePath;
@Schema(description = "扩展名", required = true)
@Deprecated
private String extendName;
}

View File

@ -1,4 +1,4 @@
package com.qiwenshare.file.dto;
package com.qiwenshare.file.dto.file;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;

View File

@ -0,0 +1,15 @@
package com.qiwenshare.file.dto.file;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Data
@Schema(name = "复制文件DTO",required = true)
public class CopyFileDTO {
@Schema(description = "用户文件id", required = true)
private long userFileId;
@Schema(description = "文件路径", required = true)
private String filePath;
}

View File

@ -1,4 +1,4 @@
package com.qiwenshare.file.dto;
package com.qiwenshare.file.dto.file;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;

View File

@ -1,4 +1,4 @@
package com.qiwenshare.file.dto;
package com.qiwenshare.file.dto.file;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;

View File

@ -1,4 +1,4 @@
package com.qiwenshare.file.dto;
package com.qiwenshare.file.dto.file;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;

View File

@ -1,4 +1,4 @@
package com.qiwenshare.file.dto;
package com.qiwenshare.file.dto.file;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;

View File

@ -1,4 +1,4 @@
package com.qiwenshare.file.dto;
package com.qiwenshare.file.dto.file;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;

View File

@ -1,9 +1,11 @@
package com.qiwenshare.file.dto.recoveryfile;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Data
@Schema(name = "批量删除回收文件DTO",required = true)
public class BatchDeleteRecoveryFileDTO {
@Schema(description="恢复文件集合")
private String recoveryFiles;
private String recoveryFileIds;
}

View File

@ -1,4 +1,4 @@
package com.qiwenshare.file.dto;
package com.qiwenshare.file.dto.recoveryfile;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;

View File

@ -0,0 +1,10 @@
package com.qiwenshare.file.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.qiwenshare.file.domain.UploadTaskDetail;
import java.util.List;
public interface UploadTaskDetailMapper extends BaseMapper<UploadTaskDetail> {
List<Integer> selectUploadedChunkNumList(String identifier);
}

View File

@ -0,0 +1,11 @@
package com.qiwenshare.file.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.qiwenshare.file.domain.UploadTask;
import com.qiwenshare.file.domain.UploadTaskDetail;
import java.util.List;
public interface UploadTaskMapper extends BaseMapper<UploadTask> {
}

View File

@ -6,15 +6,11 @@ import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.qiwenshare.common.util.DateUtil;
import com.qiwenshare.file.api.IFiletransferService;
import com.qiwenshare.file.component.FileDealComp;
import com.qiwenshare.file.domain.FileBean;
import com.qiwenshare.file.domain.StorageBean;
import com.qiwenshare.file.domain.UserFile;
import com.qiwenshare.file.dto.DownloadFileDTO;
import com.qiwenshare.file.dto.UploadFileDTO;
import com.qiwenshare.file.domain.*;
import com.qiwenshare.file.dto.file.DownloadFileDTO;
import com.qiwenshare.file.dto.file.UploadFileDTO;
import com.qiwenshare.file.dto.file.PreviewDTO;
import com.qiwenshare.file.mapper.FileMapper;
import com.qiwenshare.file.mapper.StorageMapper;
import com.qiwenshare.file.mapper.UserFileMapper;
import com.qiwenshare.file.mapper.*;
import com.qiwenshare.file.vo.file.FileListVo;
import com.qiwenshare.ufop.constant.StorageTypeEnum;
import com.qiwenshare.ufop.constant.UploadFileStatusEnum;
@ -62,6 +58,10 @@ public class FiletransferService implements IFiletransferService {
UFOPFactory ufopFactory;
@Resource
FileDealComp fileDealComp;
@Resource
UploadTaskDetailMapper UploadTaskDetailMapper;
@Resource
UploadTaskMapper uploadTaskMapper;
@Override
public void uploadFile(HttpServletRequest request, UploadFileDTO uploadFileDto, Long userId) {
@ -85,7 +85,8 @@ public class FiletransferService implements IFiletransferService {
UploadFileResult uploadFileResult = uploadFileResultList.get(i);
FileBean fileBean = new FileBean();
BeanUtil.copyProperties(uploadFileDto, fileBean);
// fileBean.setTimeStampName(uploadFile.getTimeStampName());
String relativePath = uploadFileDto.getRelativePath();
if (UploadFileStatusEnum.SUCCESS.equals(uploadFileResult.getStatus())){
fileBean.setFileUrl(uploadFileResult.getFileUrl());
fileBean.setFileSize(uploadFileResult.getFileSize());
@ -93,7 +94,7 @@ public class FiletransferService implements IFiletransferService {
fileBean.setPointCount(1);
fileMapper.insert(fileBean);
UserFile userFile = new UserFile();
String relativePath = uploadFileDto.getRelativePath();
if (relativePath.contains("/")) {
userFile.setFilePath(uploadFileDto.getFilePath() + UFOPUtils.getParentPath(relativePath) + "/");
fileDealComp.restoreParentFilePath(uploadFileDto.getFilePath() + UFOPUtils.getParentPath(relativePath) + "/", userId);
@ -118,9 +119,45 @@ public class FiletransferService implements IFiletransferService {
userFileMapper.insert(userFile);
fileDealComp.uploadESByUserFileId(userFile.getUserFileId());
}
LambdaQueryWrapper<UploadTaskDetail> lambdaQueryWrapper = new LambdaQueryWrapper<>();
lambdaQueryWrapper.eq(UploadTaskDetail::getIdentifier, uploadFileDto.getIdentifier());
UploadTaskDetailMapper.delete(lambdaQueryWrapper);
LambdaUpdateWrapper<UploadTask> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
lambdaUpdateWrapper.set(UploadTask::getUploadStatus, UploadFileStatusEnum.SUCCESS.getCode())
.eq(UploadTask::getIdentifier, uploadFileDto.getIdentifier());
uploadTaskMapper.update(null, lambdaUpdateWrapper);
} else if (UploadFileStatusEnum.UNCOMPLATE.equals(uploadFileResult.getStatus())) {
UploadTaskDetail UploadTaskDetail = new UploadTaskDetail();
UploadTaskDetail.setFilePath(uploadFileDto.getFilePath());
if (relativePath.contains("/")) {
UploadTaskDetail.setFilePath(uploadFileDto.getFilePath() + UFOPUtils.getParentPath(relativePath) + "/");
} else {
UploadTaskDetail.setFilePath(uploadFileDto.getFilePath());
}
UploadTaskDetail.setFilename(uploadFileDto.getFilename());
UploadTaskDetail.setChunkNumber(uploadFileDto.getChunkNumber());
UploadTaskDetail.setChunkSize((int)uploadFileDto.getChunkSize());
UploadTaskDetail.setRelativePath(uploadFileDto.getRelativePath());
UploadTaskDetail.setTotalChunks(uploadFileDto.getTotalChunks());
UploadTaskDetail.setTotalSize((int)uploadFileDto.getTotalSize());
UploadTaskDetail.setIdentifier(uploadFileDto.getIdentifier());
UploadTaskDetailMapper.insert(UploadTaskDetail);
} else if (UploadFileStatusEnum.FAIL.equals(uploadFileResult.getStatus())) {
LambdaQueryWrapper<UploadTaskDetail> lambdaQueryWrapper = new LambdaQueryWrapper<>();
lambdaQueryWrapper.eq(UploadTaskDetail::getIdentifier, uploadFileDto.getIdentifier());
UploadTaskDetailMapper.delete(lambdaQueryWrapper);
LambdaUpdateWrapper<UploadTask> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
lambdaUpdateWrapper.set(UploadTask::getUploadStatus, UploadFileStatusEnum.FAIL.getCode())
.eq(UploadTask::getIdentifier, uploadFileDto.getIdentifier());
uploadTaskMapper.update(null, lambdaUpdateWrapper);
}
}
}
@Override

View File

@ -0,0 +1,22 @@
package com.qiwenshare.file.service;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qiwenshare.file.api.IUploadTaskDetailService;
import com.qiwenshare.file.domain.UploadTaskDetail;
import com.qiwenshare.file.mapper.UploadTaskDetailMapper;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.List;
@Service
public class UploadTaskDetailService extends ServiceImpl<UploadTaskDetailMapper, UploadTaskDetail> implements IUploadTaskDetailService {
@Resource
UploadTaskDetailMapper uploadTaskDetailMapper;
@Override
public List<Integer> getUploadedChunkNumList(String identifier) {
return uploadTaskDetailMapper.selectUploadedChunkNumList(identifier);
}
}

View File

@ -0,0 +1,19 @@
package com.qiwenshare.file.service;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qiwenshare.file.api.IUploadTaskDetailService;
import com.qiwenshare.file.api.IUploadTaskService;
import com.qiwenshare.file.domain.UploadTask;
import com.qiwenshare.file.domain.UploadTaskDetail;
import com.qiwenshare.file.mapper.UploadTaskDetailMapper;
import com.qiwenshare.file.mapper.UploadTaskMapper;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.List;
@Service
public class UploadTaskService extends ServiceImpl<UploadTaskMapper, UploadTask> implements IUploadTaskService {
}

View File

@ -0,0 +1,15 @@
package com.qiwenshare.file.test;
import com.alibaba.fastjson.JSON;
import java.util.ArrayList;
import java.util.List;
public class test {
public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
System.out.println(JSON.toJSONString(list));
}
}

View File

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.qiwenshare.file.mapper.UploadTaskDetailMapper">
<select id="selectUploadedChunkNumList" parameterType="java.lang.String" resultType="java.lang.Integer">
select chunkNumber from UploadTaskDetail
where identifier = #{identifier}
order by chunkNumber asc
</select>
</mapper>