feat:增加工具类
This commit is contained in:
@@ -0,0 +1,98 @@
|
|||||||
|
package com.tiesheng.util.pojos;
|
||||||
|
|
||||||
|
import cn.hutool.core.date.DateUtil;
|
||||||
|
import cn.hutool.core.io.FileUtil;
|
||||||
|
import cn.hutool.core.util.IdUtil;
|
||||||
|
import cn.hutool.core.util.StrUtil;
|
||||||
|
|
||||||
|
public class FileUploadPath {
|
||||||
|
|
||||||
|
public static String UPLOAD_FOLDER = "/upload/";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 绝对路径
|
||||||
|
*/
|
||||||
|
private String absolutePath;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 访问路径
|
||||||
|
*/
|
||||||
|
private String httpPath;
|
||||||
|
|
||||||
|
private FileUploadPath() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获得一个文件路径
|
||||||
|
*
|
||||||
|
* @param fileName
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static FileUploadPath get(String fileName) {
|
||||||
|
FileUploadPath pathBean = new FileUploadPath();
|
||||||
|
|
||||||
|
String tempPath = fileName;
|
||||||
|
if (!StrUtil.startWith(tempPath, UPLOAD_FOLDER)) {
|
||||||
|
tempPath = UPLOAD_FOLDER + DateUtil.format(DateUtil.date(), "yyyy-MM") + "/" + fileName;
|
||||||
|
}
|
||||||
|
pathBean.setHttpPath(tempPath);
|
||||||
|
pathBean.setAbsolutePath(String.format("%s/static%s", System.getProperty("user.dir"), tempPath));
|
||||||
|
|
||||||
|
return pathBean;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 随机生成一个文件路径
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static FileUploadPath random() {
|
||||||
|
return get(IdUtil.simpleUUID());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取一个目录
|
||||||
|
*
|
||||||
|
* @param folder
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static FileUploadPath folder(String folder) {
|
||||||
|
FileUploadPath pathBean = new FileUploadPath();
|
||||||
|
|
||||||
|
String tempFolder = folder;
|
||||||
|
if (!StrUtil.startWith(tempFolder, UPLOAD_FOLDER)) {
|
||||||
|
tempFolder = UPLOAD_FOLDER + tempFolder;
|
||||||
|
}
|
||||||
|
if (!StrUtil.endWith(folder, "/")) {
|
||||||
|
tempFolder = tempFolder + "/";
|
||||||
|
}
|
||||||
|
pathBean.setHttpPath(tempFolder);
|
||||||
|
pathBean.setAbsolutePath(String.format("%s/static%s", System.getProperty("user.dir"), tempFolder));
|
||||||
|
FileUtil.mkParentDirs(pathBean.getAbsolutePath());
|
||||||
|
|
||||||
|
return pathBean;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
// setter\getter
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
public String getAbsolutePath() {
|
||||||
|
return absolutePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAbsolutePath(String absolutePath) {
|
||||||
|
this.absolutePath = absolutePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getHttpPath() {
|
||||||
|
return httpPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHttpPath(String httpPath) {
|
||||||
|
this.httpPath = httpPath;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -38,4 +38,11 @@ public interface TieshengWebConfigurer {
|
|||||||
return ApiResp.respCust(ApiRespEnum.ServerError);
|
return ApiResp.respCust(ApiRespEnum.ServerError);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加文件校验
|
||||||
|
*/
|
||||||
|
default void uploadFileCheck(String fileExt) {
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,117 @@
|
|||||||
|
package com.tiesheng.core.controller.tool;
|
||||||
|
|
||||||
|
|
||||||
|
import cn.hutool.captcha.LineCaptcha;
|
||||||
|
import cn.hutool.core.util.IdUtil;
|
||||||
|
import com.tiesheng.annotation.token.TokenIgnore;
|
||||||
|
import com.tiesheng.core.pojos.dto.ImageCodeDTO;
|
||||||
|
import com.tiesheng.core.pojos.vo.PicVerifyVo;
|
||||||
|
import com.tiesheng.core.service.FileUploadService;
|
||||||
|
import com.tiesheng.core.service.TimedCacheService;
|
||||||
|
import com.tiesheng.util.pojos.ApiResp;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 工具类
|
||||||
|
*
|
||||||
|
* @author hao
|
||||||
|
*/
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/tool")
|
||||||
|
public class ToolController {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
TimedCacheService timedCacheService;
|
||||||
|
@Autowired
|
||||||
|
FileUploadService fileUploadService;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 图片验证码
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@TokenIgnore
|
||||||
|
@GetMapping("/code/image")
|
||||||
|
public ApiResp<PicVerifyVo> picVerifyV2(ImageCodeDTO dto) {
|
||||||
|
|
||||||
|
LineCaptcha lineCaptcha = dto.lineCaptcha();
|
||||||
|
PicVerifyVo vo = new PicVerifyVo();
|
||||||
|
vo.setBase64(lineCaptcha.getImageBase64Data());
|
||||||
|
vo.setKey(IdUtil.simpleUUID());
|
||||||
|
timedCacheService.setImageCode(vo.getKey(), lineCaptcha.getCode());
|
||||||
|
|
||||||
|
return ApiResp.respOK(vo);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 上传整个文件
|
||||||
|
*
|
||||||
|
* @param file
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@TokenIgnore
|
||||||
|
@PostMapping("/file/whole_upload")
|
||||||
|
public ApiResp<String> fileWholeUpload(@RequestParam("file") MultipartFile file) {
|
||||||
|
String filePath = fileUploadService.saveMultipartFile(file);
|
||||||
|
return ApiResp.respOK(filePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 上传超大文件,建议超过20M的使用这个方法
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@TokenIgnore
|
||||||
|
@PostMapping(value = "/file/chunk_start")
|
||||||
|
public ApiResp<String> fileChunkStart(String fileExt) {
|
||||||
|
fileUploadService.chunkStart(fileExt);
|
||||||
|
return ApiResp.respOK("");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 校验文件块
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@TokenIgnore
|
||||||
|
@PostMapping("/file/chunk_check")
|
||||||
|
public ApiResp<Boolean> fileChunkCheck(String fileMd5, Integer chunk) {
|
||||||
|
boolean exist = fileUploadService.chunkCheck(fileMd5, chunk);
|
||||||
|
return ApiResp.respOK(exist);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 上传文件块
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@TokenIgnore
|
||||||
|
@PostMapping("/file/chunk_upload")
|
||||||
|
public ApiResp<String> fileChunkUpload(@RequestParam("file") MultipartFile file, String fileMd5, Integer chunk) {
|
||||||
|
fileUploadService.chunkUpload(file, fileMd5, chunk);
|
||||||
|
return ApiResp.respOK("");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 合并文件
|
||||||
|
*
|
||||||
|
* @param fileMd5
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@TokenIgnore
|
||||||
|
@PostMapping("/file/chunk_merge")
|
||||||
|
public ApiResp<String> fileChunkMerge(String fileMd5) {
|
||||||
|
String path = fileUploadService.chunkMerge(fileMd5);
|
||||||
|
return ApiResp.respOK(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
package com.tiesheng.core.pojos.dto;
|
||||||
|
|
||||||
|
import cn.hutool.captcha.CaptchaUtil;
|
||||||
|
import cn.hutool.captcha.LineCaptcha;
|
||||||
|
import cn.hutool.captcha.generator.RandomGenerator;
|
||||||
|
|
||||||
|
public class ImageCodeDTO {
|
||||||
|
|
||||||
|
private Integer lineCount;
|
||||||
|
private Integer width;
|
||||||
|
private Integer height;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构建线条图形码
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public LineCaptcha lineCaptcha() {
|
||||||
|
if (lineCount == null || lineCount < 100) {
|
||||||
|
lineCount = 100;
|
||||||
|
}
|
||||||
|
if (width == null) {
|
||||||
|
width = 220;
|
||||||
|
}
|
||||||
|
if (height == null) {
|
||||||
|
height = 62;
|
||||||
|
}
|
||||||
|
LineCaptcha lineCaptcha = CaptchaUtil.createLineCaptcha(width, height, 4, lineCount);
|
||||||
|
lineCaptcha.setGenerator(new RandomGenerator("0123456789", 4));
|
||||||
|
|
||||||
|
return lineCaptcha;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
// setter\getter
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
public Integer getLineCount() {
|
||||||
|
return lineCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLineCount(Integer lineCount) {
|
||||||
|
this.lineCount = lineCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getWidth() {
|
||||||
|
return width;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setWidth(Integer width) {
|
||||||
|
this.width = width;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getHeight() {
|
||||||
|
return height;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHeight(Integer height) {
|
||||||
|
this.height = height;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
package com.tiesheng.core.pojos.vo;
|
||||||
|
|
||||||
|
public class PicVerifyVo {
|
||||||
|
|
||||||
|
private String base64;
|
||||||
|
private String key;
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
// setter\getter
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
public String getBase64() {
|
||||||
|
return base64;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBase64(String base64) {
|
||||||
|
this.base64 = base64;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getKey() {
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setKey(String key) {
|
||||||
|
this.key = key;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,166 @@
|
|||||||
|
package com.tiesheng.core.service;
|
||||||
|
|
||||||
|
import cn.hutool.core.io.FileTypeUtil;
|
||||||
|
import cn.hutool.core.io.FileUtil;
|
||||||
|
import cn.hutool.core.io.IoUtil;
|
||||||
|
import com.tiesheng.core.config.web.TieshengWebConfigurer;
|
||||||
|
import com.tiesheng.util.exception.ApiException;
|
||||||
|
import com.tiesheng.util.pojos.FileUploadPath;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author hao
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
public class FileUploadService {
|
||||||
|
|
||||||
|
@Autowired(required = false)
|
||||||
|
TieshengWebConfigurer tieshengWebConfigurer;
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
// 方法
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保存文件
|
||||||
|
*
|
||||||
|
* @param file
|
||||||
|
*/
|
||||||
|
public String saveMultipartFile(MultipartFile file) {
|
||||||
|
try {
|
||||||
|
|
||||||
|
String fileType = FileTypeUtil.getType(file.getInputStream(), file.getOriginalFilename());
|
||||||
|
tieshengWebConfigurer.uploadFileCheck(fileType);
|
||||||
|
|
||||||
|
FileUploadPath filePath = FileUploadPath.random();
|
||||||
|
|
||||||
|
InputStream stream = file.getInputStream();
|
||||||
|
FileUtil.writeFromStream(stream, filePath.getAbsolutePath());
|
||||||
|
IoUtil.close(stream);
|
||||||
|
|
||||||
|
return filePath.getHttpPath();
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new ApiException("文件流读取失败:" + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
// 文件分包上传
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查待上传文件是否存在
|
||||||
|
*
|
||||||
|
* @param fileExt
|
||||||
|
*/
|
||||||
|
public void chunkStart(String fileExt) {
|
||||||
|
tieshengWebConfigurer.uploadFileCheck(fileExt);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查块文件
|
||||||
|
*
|
||||||
|
* @param fileMd5
|
||||||
|
* @param chunk
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public boolean chunkCheck(String fileMd5, Integer chunk) {
|
||||||
|
FileUploadPath folder = FileUploadPath.folder(fileMd5);
|
||||||
|
File chunkFile = FileUtil.file(folder.getAbsolutePath(), chunk.toString());
|
||||||
|
return chunkFile.exists();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 块文件上传
|
||||||
|
*
|
||||||
|
* @param file
|
||||||
|
* @param fileMd5
|
||||||
|
* @param chunk
|
||||||
|
*/
|
||||||
|
public void chunkUpload(MultipartFile file, String fileMd5, Integer chunk) {
|
||||||
|
if (file == null) {
|
||||||
|
throw new ApiException("请选择文件后上传");
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 块文件
|
||||||
|
FileUploadPath folder = FileUploadPath.folder(fileMd5);
|
||||||
|
File chunkfile = new File(folder.getAbsolutePath(), chunk.toString());
|
||||||
|
InputStream stream = file.getInputStream();
|
||||||
|
FileUtil.writeFromStream(stream, chunkfile);
|
||||||
|
IoUtil.close(stream);
|
||||||
|
} catch (Exception ignored) {
|
||||||
|
throw new ApiException("块文件上传失败");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 合并块文件
|
||||||
|
*
|
||||||
|
* @param fileMd5
|
||||||
|
* @param fileExt
|
||||||
|
*/
|
||||||
|
public String chunkMerge(String fileMd5) {
|
||||||
|
|
||||||
|
// 1,获取块文件的路径
|
||||||
|
FileUploadPath folder = FileUploadPath.folder(fileMd5);
|
||||||
|
|
||||||
|
// 2,生成保存文件路径
|
||||||
|
FileUploadPath uploadPath = FileUploadPath.random();
|
||||||
|
|
||||||
|
// 3,如果文件不存在
|
||||||
|
if (FileUtil.exist(folder.getAbsolutePath())) {
|
||||||
|
|
||||||
|
// 4,获取块文件,此列表是已经排好序的列表
|
||||||
|
List<File> chunkFiles = getChunkFiles(new File(folder.getAbsolutePath()));
|
||||||
|
|
||||||
|
// 5,合并文件
|
||||||
|
File newFile = FileUtil.newFile(uploadPath.getAbsolutePath());
|
||||||
|
for (File file : chunkFiles) {
|
||||||
|
byte[] bytes = FileUtil.readBytes(file);
|
||||||
|
FileUtil.writeBytes(bytes, newFile, 0, bytes.length, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 6,删除块文件目录
|
||||||
|
FileUtil.del(folder.getAbsolutePath());
|
||||||
|
}
|
||||||
|
|
||||||
|
return uploadPath.getHttpPath();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取所有块文件
|
||||||
|
*
|
||||||
|
* @param chunkFileFolder
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private List<File> getChunkFiles(File chunkFileFolder) {
|
||||||
|
|
||||||
|
//获取路径下的所有块文件
|
||||||
|
File[] chunkFiles = chunkFileFolder.listFiles();
|
||||||
|
if (chunkFiles == null) {
|
||||||
|
return new ArrayList<>();
|
||||||
|
}
|
||||||
|
//将文件数组转成list,并排序
|
||||||
|
List<File> chunkFileList = new ArrayList<>(Arrays.asList(chunkFiles));
|
||||||
|
//排序
|
||||||
|
chunkFileList.sort((o1, o2) -> {
|
||||||
|
if (Integer.parseInt(o1.getName()) > Integer.parseInt(o2.getName())) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
});
|
||||||
|
return chunkFileList;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,248 +0,0 @@
|
|||||||
package com.tiesheng.core.service;
|
|
||||||
|
|
||||||
import cn.hutool.core.date.DateUtil;
|
|
||||||
import cn.hutool.core.io.FileTypeUtil;
|
|
||||||
import cn.hutool.core.io.FileUtil;
|
|
||||||
import cn.hutool.core.io.IoUtil;
|
|
||||||
import cn.hutool.core.io.file.FileNameUtil;
|
|
||||||
import cn.hutool.core.util.IdUtil;
|
|
||||||
import cn.hutool.core.util.StrUtil;
|
|
||||||
import com.tiesheng.util.exception.ApiException;
|
|
||||||
import org.springframework.core.io.ClassPathResource;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@Service
|
|
||||||
public class ToolsFileService {
|
|
||||||
|
|
||||||
private String ext;
|
|
||||||
private String absPath;
|
|
||||||
private String folder = "/upload";
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
|
||||||
// 方法
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 检查文件类型
|
|
||||||
*
|
|
||||||
* @param fileType
|
|
||||||
*/
|
|
||||||
private void checkFileType(String fileType) {
|
|
||||||
if (!StrUtil.isEmpty(ext) && !StrUtil.split(ext, ",").contains(fileType)) {
|
|
||||||
throw new ApiException("该文件格式不支持上传");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取upload目录的绝对路径
|
|
||||||
*
|
|
||||||
* @param dest 文件名称,如果没有/upload,则会添加/upload
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public String getUploadAbsPath(String dest) {
|
|
||||||
String destFile = absPath;
|
|
||||||
if (StrUtil.isEmpty(destFile)) {
|
|
||||||
ClassPathResource classPathResource = new ClassPathResource("static");
|
|
||||||
File rootFile = new File(classPathResource.getPath());
|
|
||||||
destFile = rootFile.getAbsolutePath();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!StrUtil.startWith(dest, folder)) {
|
|
||||||
destFile = destFile + folder;
|
|
||||||
}
|
|
||||||
|
|
||||||
return String.format("%s/%s", destFile, dest);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 保存文件
|
|
||||||
*
|
|
||||||
* @param file
|
|
||||||
*/
|
|
||||||
public String saveMultipartFile(MultipartFile file) {
|
|
||||||
try {
|
|
||||||
|
|
||||||
// 获取文件类型
|
|
||||||
String fileType = FileNameUtil.extName(file.getOriginalFilename());
|
|
||||||
if (StrUtil.isEmpty(fileType)) {
|
|
||||||
fileType = FileTypeUtil.getType(file.getInputStream(), file.getOriginalFilename());
|
|
||||||
}
|
|
||||||
if (StrUtil.isEmpty(fileType)) {
|
|
||||||
fileType = "unknow";
|
|
||||||
}
|
|
||||||
checkFileType(fileType);
|
|
||||||
|
|
||||||
String filePath = String.format("/%s/%s.%s", DateUtil.format(DateUtil.date(), "yyyy-MM"), IdUtil.simpleUUID(), fileType);
|
|
||||||
|
|
||||||
InputStream stream = file.getInputStream();
|
|
||||||
FileUtil.writeFromStream(stream, getUploadAbsPath(filePath));
|
|
||||||
IoUtil.close(stream);
|
|
||||||
|
|
||||||
return folder + filePath;
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new ApiException("文件流读取失败:" + e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
|
||||||
// 文件分包上传
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 得到块文件的根目录,上传完成之后便于删除
|
|
||||||
*
|
|
||||||
* @param fileMd5
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
private String getChunkFolder(String fileMd5) {
|
|
||||||
String folder = getUploadAbsPath(fileMd5);
|
|
||||||
FileUtil.mkdir(folder);
|
|
||||||
return folder;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 检查待上传文件是否存在
|
|
||||||
*
|
|
||||||
* @param fileMd5
|
|
||||||
* @param fileExt
|
|
||||||
*/
|
|
||||||
public void register(String fileMd5, String fileExt) {
|
|
||||||
checkFileType(fileExt);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 检查块文件
|
|
||||||
*
|
|
||||||
* @param fileMd5
|
|
||||||
* @param chunk
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public boolean checkChunk(String fileMd5, Integer chunk) {
|
|
||||||
// 1,得到块文件所在路径
|
|
||||||
String chunkFileFolder = getChunkFolder(fileMd5);
|
|
||||||
// 2,块文件的文件名称以1,2,3..序号命名,没有扩展名
|
|
||||||
File chunkFile = FileUtil.file(chunkFileFolder, chunk.toString());
|
|
||||||
return chunkFile.exists();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 块文件上传
|
|
||||||
*
|
|
||||||
* @param file
|
|
||||||
* @param fileMd5
|
|
||||||
* @param chunk
|
|
||||||
*/
|
|
||||||
public void uploadChunk(MultipartFile file, String fileMd5, Integer chunk) {
|
|
||||||
if (file == null) {
|
|
||||||
throw new ApiException("请选择文件后上传");
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
// 块文件
|
|
||||||
File chunkfile = new File(getChunkFolder(fileMd5), chunk.toString());
|
|
||||||
InputStream stream = file.getInputStream();
|
|
||||||
FileUtil.writeFromStream(stream, chunkfile);
|
|
||||||
IoUtil.close(stream);
|
|
||||||
} catch (Exception ignored) {
|
|
||||||
throw new ApiException("块文件上传失败");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 合并块文件
|
|
||||||
*
|
|
||||||
* @param fileMd5
|
|
||||||
* @param fileExt
|
|
||||||
*/
|
|
||||||
public String mergeChunks(String fileMd5, String fileExt) {
|
|
||||||
|
|
||||||
// 1,获取块文件的路径
|
|
||||||
File chunkFileFolder = new File(getChunkFolder(fileMd5));
|
|
||||||
|
|
||||||
// 2,合并文件目录
|
|
||||||
String filePath = String.format("/%s/%s.%s", DateUtil.format(DateUtil.date(), "yyyy-MM"), fileMd5, fileExt);
|
|
||||||
String outputPath = getUploadAbsPath(filePath);
|
|
||||||
|
|
||||||
// 3,如果文件不存在
|
|
||||||
if (!FileUtil.exist(outputPath)) {
|
|
||||||
|
|
||||||
// 4,获取块文件,此列表是已经排好序的列表
|
|
||||||
List<File> chunkFiles = getChunkFiles(chunkFileFolder);
|
|
||||||
|
|
||||||
// 5,合并文件
|
|
||||||
File newFile = FileUtil.newFile(outputPath);
|
|
||||||
for (File file : chunkFiles) {
|
|
||||||
byte[] bytes = FileUtil.readBytes(file);
|
|
||||||
FileUtil.writeBytes(bytes, newFile, 0, bytes.length, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 6,删除块文件目录
|
|
||||||
FileUtil.del(chunkFileFolder);
|
|
||||||
|
|
||||||
return folder + filePath;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取所有块文件
|
|
||||||
*
|
|
||||||
* @param chunkFileFolder
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
private List<File> getChunkFiles(File chunkFileFolder) {
|
|
||||||
|
|
||||||
//获取路径下的所有块文件
|
|
||||||
File[] chunkFiles = chunkFileFolder.listFiles();
|
|
||||||
if (chunkFiles == null) {
|
|
||||||
return new ArrayList<>();
|
|
||||||
}
|
|
||||||
//将文件数组转成list,并排序
|
|
||||||
List<File> chunkFileList = new ArrayList<>(Arrays.asList(chunkFiles));
|
|
||||||
//排序
|
|
||||||
chunkFileList.sort((o1, o2) -> {
|
|
||||||
if (Integer.parseInt(o1.getName()) > Integer.parseInt(o2.getName())) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
});
|
|
||||||
return chunkFileList;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
|
||||||
// setter、getter
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
public String getAbsPath() {
|
|
||||||
return absPath;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setAbsPath(String absPath) {
|
|
||||||
this.absPath = absPath;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getExt() {
|
|
||||||
return ext;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setExt(String ext) {
|
|
||||||
this.ext = ext;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getFolder() {
|
|
||||||
return folder;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setFolder(String folder) {
|
|
||||||
this.folder = folder;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user