diff --git a/src/main/java/com/zilber/boot/file/controller/FileUploadController.java b/src/main/java/com/zilber/boot/file/controller/FileUploadController.java new file mode 100644 index 0000000..6445183 --- /dev/null +++ b/src/main/java/com/zilber/boot/file/controller/FileUploadController.java @@ -0,0 +1,89 @@ +package com.zilber.boot.file.controller; + +import com.aliyun.oss.model.*; +import com.zilber.boot.file.entity.*; +import com.zilber.boot.file.service.UploadUtils; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.multipart.MultipartFile; +import reactor.util.annotation.Nullable; + +import java.io.IOException; +import java.util.Map; + +@Validated +@RestController +@RequiredArgsConstructor +@RequestMapping("/file") +@Api(tags = "基本功能管理") +public class FileUploadController { + + private final UploadUtils uploadUtils; + + @ApiOperation("文件上传服务器") + @PostMapping("/upload") + public Map uploadFile(MultipartFile file) { + return uploadUtils.upload(file); + } + + @ApiOperation("分片上传服务器") + @PostMapping("/slice") + public ETag sliceUploads(FileUploadsRequestDTO param) { + return uploadUtils.sliceUploads(param); + } + + @ApiOperation("分片上传检测-服务器") + @PostMapping("/check") + public PartList fileCheck(String fileMd5, String UUID) throws IOException { + return uploadUtils.fileCheck(fileMd5, UUID); + } + + @ApiOperation("分片上传合成-服务器") + @PostMapping("/compose") + public Complete compose(@RequestBody ComposeDTO dto) { + return uploadUtils.compose(dto.getUuid(), dto.getType(), dto.getFileMd5()); + } + + @ApiOperation("文件上传oss服务器") + @PostMapping("/oss/upload") + public Map uploadFileToOss(MultipartFile file) { + return uploadUtils.upload(file, null); + } + + @ApiOperation("分片上传初始化-oss服务器") + @PostMapping("/oss/initiate") + public OssPartUpload initiate(String fileName) { + return uploadUtils.InitiateMultipartUpload(fileName, null, null); + } + + @ApiOperation("分片上传-oss服务器") + @PostMapping("/oss/slice") + public PartETag sliceUploads(OssPartUpload upload) { + return uploadUtils.uploadPart(upload); + } + + @ApiOperation("分片上传检测-oss服务器") + @PostMapping("/oss/check") + public PartListing PartListing(OssListParts parts) { + return uploadUtils.list(parts); + } + + @ApiOperation("分片上传合成-oss服务器") + @PostMapping("/oss/compose") + public CompleteMultipartUploadResult compose(@RequestBody OssComplete complete) { + return uploadUtils.completeUpload(complete); + } + + @ApiOperation("分片上传取消-oss服务器") + @PostMapping("/oss/abort") + public void abort(OssCancel cancel) { + uploadUtils.abortUpload(cancel); + } + +} \ No newline at end of file diff --git a/src/main/java/com/zilber/boot/file/dao/FileDao.java b/src/main/java/com/zilber/boot/file/dao/FileDao.java index c8d16de..dd0a0ab 100644 --- a/src/main/java/com/zilber/boot/file/dao/FileDao.java +++ b/src/main/java/com/zilber/boot/file/dao/FileDao.java @@ -10,10 +10,10 @@ import java.util.Map; @Mapper public interface FileDao { - @Select("SELECT url, type FROM file WHERE md5 = #{md5} LIMIT 1") - Map listFileUrl(@Param("md5") String md5); + @Select("SELECT url, type FROM file WHERE md5 = #{md5} AND location = #{location} LIMIT 1") + Map listFileUrl(@Param("md5") String md5, @Param("location") Integer location); - @Insert("INSERT INTO file(md5, url, type) VALUES (#{md5}, #{url}, #{type})") - void addFile(@Param("md5") String md5,@Param("url") String url,@Param("type") Integer type); + @Insert("INSERT INTO file(md5, url, type, location) VALUES (#{md5}, #{url}, #{type},#{location})") + void addFile(@Param("md5") String md5,@Param("url") String url,@Param("type") Integer type,@Param("location") Integer location); } diff --git a/src/main/java/com/zilber/boot/file/entity/Complete.java b/src/main/java/com/zilber/boot/file/entity/Complete.java new file mode 100644 index 0000000..27a64a7 --- /dev/null +++ b/src/main/java/com/zilber/boot/file/entity/Complete.java @@ -0,0 +1,29 @@ +package com.zilber.boot.file.entity; + +import lombok.Data; + +/** + * @Author LJX + * @TIME 2023-01-10 14:32 + * @PROJECT boot + * created by Intellij IDEA + * Description + */ +@Data +public class Complete { + + private String bucketName; + + private String key; + + private String location; + + private String eTag; + + private String versionId; + + private String name; + + private Integer type; + +} diff --git a/src/main/java/com/zilber/boot/file/entity/ComposeDTO.java b/src/main/java/com/zilber/boot/file/entity/ComposeDTO.java new file mode 100644 index 0000000..65a215c --- /dev/null +++ b/src/main/java/com/zilber/boot/file/entity/ComposeDTO.java @@ -0,0 +1,21 @@ +package com.zilber.boot.file.entity; + +import lombok.Data; + +/** + * @Author LJX + * @TIME 2022-10-12 13:16 + * @PROJECT cppcc + * created by Intellij IDEA + * Description + */ +@Data +public class ComposeDTO { + + private String uuid; + + private String fileMd5; + + private String type; + +} diff --git a/src/main/java/com/zilber/boot/file/entity/ETag.java b/src/main/java/com/zilber/boot/file/entity/ETag.java new file mode 100644 index 0000000..6d19a4a --- /dev/null +++ b/src/main/java/com/zilber/boot/file/entity/ETag.java @@ -0,0 +1,20 @@ +package com.zilber.boot.file.entity; + +import lombok.Data; + +/** + * @Author LJX + * @TIME 2023-01-10 14:18 + * @PROJECT boot + * created by Intellij IDEA + * Description + */ +@Data +public class ETag { + + private int partNumber; + private String eTag; + private long partSize; + private Long partCRC; + +} diff --git a/src/main/java/com/zilber/boot/file/entity/FileCheckDTO.java b/src/main/java/com/zilber/boot/file/entity/FileCheckDTO.java new file mode 100644 index 0000000..d5e8530 --- /dev/null +++ b/src/main/java/com/zilber/boot/file/entity/FileCheckDTO.java @@ -0,0 +1,38 @@ +package com.zilber.boot.file.entity; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.util.Map; + +/** + * @Author LJX + * @TIME 2022-10-11 11:04 + * @PROJECT cppcc + * created by Intellij IDEA + * Description + */ +@Data +@ApiModel("文件检测") +public class FileCheckDTO { + + @ApiModelProperty(name = "文件路径") + private String url; + + @ApiModelProperty(name = "文件类型") + private Integer type; + + @ApiModelProperty(name = "文件是否存在") + private Boolean exist; + + @ApiModelProperty(name = "文件是否已上传") + private Boolean uploaded; + + @ApiModelProperty(name = "文件总块数") + private Long chunks; + + @ApiModelProperty(name = "文件块信息") + private Map chunkInfo; + +} diff --git a/src/main/java/com/zilber/boot/file/entity/FileUploadDTO.java b/src/main/java/com/zilber/boot/file/entity/FileUploadDTO.java new file mode 100644 index 0000000..5a02331 --- /dev/null +++ b/src/main/java/com/zilber/boot/file/entity/FileUploadDTO.java @@ -0,0 +1,27 @@ +package com.zilber.boot.file.entity; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; + +import java.util.Map; + +@Getter +@Setter +@Builder +@NoArgsConstructor +@AllArgsConstructor +@ApiModel("文件上传返回") +public class FileUploadDTO { + + @ApiModelProperty("文件状态:1-完成 0-失败或未完成") + private Integer uploadComplete; + + private Map chunkMd5Info; + + @ApiModelProperty("文件名") + private String name; + + @ApiModelProperty("文件地址") + private String url; +} diff --git a/src/main/java/com/zilber/boot/file/entity/FileUploadRequestDTO.java b/src/main/java/com/zilber/boot/file/entity/FileUploadRequestDTO.java new file mode 100644 index 0000000..c803e41 --- /dev/null +++ b/src/main/java/com/zilber/boot/file/entity/FileUploadRequestDTO.java @@ -0,0 +1,38 @@ +package com.zilber.boot.file.entity; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import org.springframework.web.multipart.MultipartFile; + +@Data +@ApiModel("文件切片") +public class FileUploadRequestDTO { + + //文件 + @ApiModelProperty("文件") + private MultipartFile file; + + //块大小 + @ApiModelProperty("文件块大小") + private Long chunkSize; + + //当前块数 + @ApiModelProperty("当前文件块") + private Long chunk; + + //总块数 + @ApiModelProperty("文件总块数") + private Long chunks; + + @ApiModelProperty("文件类型") + private String type; + + @ApiModelProperty("文件名称") + private String name; + + @ApiModelProperty("md5") + private String md5; + + /*private String path;*/ +} diff --git a/src/main/java/com/zilber/boot/file/entity/FileUploadsDTO.java b/src/main/java/com/zilber/boot/file/entity/FileUploadsDTO.java new file mode 100644 index 0000000..2c30e86 --- /dev/null +++ b/src/main/java/com/zilber/boot/file/entity/FileUploadsDTO.java @@ -0,0 +1,30 @@ +package com.zilber.boot.file.entity; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; + +@Getter +@Setter +@Builder +@NoArgsConstructor +@AllArgsConstructor +@ApiModel("文件上传返回") +public class FileUploadsDTO { + + @ApiModelProperty("文件状态:1-完成 0-失败或未完成") + private Integer uploadComplete; + + //块大小 + @ApiModelProperty("文件块大小") + private Long chunkSize; + + //当前块数 + @ApiModelProperty("当前文件块") + private Long chunk; + + //总块数 + @ApiModelProperty("文件总块数") + private Long chunks; + +} diff --git a/src/main/java/com/zilber/boot/file/entity/FileUploadsRequestDTO.java b/src/main/java/com/zilber/boot/file/entity/FileUploadsRequestDTO.java new file mode 100644 index 0000000..6084a5a --- /dev/null +++ b/src/main/java/com/zilber/boot/file/entity/FileUploadsRequestDTO.java @@ -0,0 +1,47 @@ +package com.zilber.boot.file.entity; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import org.springframework.web.multipart.MultipartFile; + +@Data +@ApiModel("文件切片") +public class FileUploadsRequestDTO { + + //文件 + @ApiModelProperty("文件") + private MultipartFile file; + + //块大小 + @ApiModelProperty("文件块大小") + private Long chunkSize; + + //当前块数 + @ApiModelProperty("当前文件块") + private Long chunk; + + //总块数 + @ApiModelProperty("文件总块数") + private Long chunks; + + @ApiModelProperty("文件类型") + private String type; + + @ApiModelProperty("文件名称") + private String name; + + @ApiModelProperty("文件大小") + private Long size; + +// @ApiModelProperty("分片md5") +// private String sliceMd5; +// +// @ApiModelProperty("md5") +// private String md5; + + @ApiModelProperty("uuid") + private String UUID; + + /*private String path;*/ +} diff --git a/src/main/java/com/zilber/boot/file/entity/OssComplete.java b/src/main/java/com/zilber/boot/file/entity/OssComplete.java index 8e09398..3665667 100644 --- a/src/main/java/com/zilber/boot/file/entity/OssComplete.java +++ b/src/main/java/com/zilber/boot/file/entity/OssComplete.java @@ -32,6 +32,6 @@ public class OssComplete extends OssProperties{ @NotNull(message = "tag列表不能为空") @ApiModelProperty("tag列表") - private List tags; + private List tags; } diff --git a/src/main/java/com/zilber/boot/file/entity/OssListParts.java b/src/main/java/com/zilber/boot/file/entity/OssListParts.java index 62f733f..e7acd48 100644 --- a/src/main/java/com/zilber/boot/file/entity/OssListParts.java +++ b/src/main/java/com/zilber/boot/file/entity/OssListParts.java @@ -31,6 +31,6 @@ public class OssListParts extends OssProperties { private Integer maxParts = 100; @ApiModelProperty(value = "开始块数") - private Integer partNumberMarker = 0; + private Integer partNumberMarker = 1; } diff --git a/src/main/java/com/zilber/boot/file/entity/PartList.java b/src/main/java/com/zilber/boot/file/entity/PartList.java new file mode 100644 index 0000000..e814980 --- /dev/null +++ b/src/main/java/com/zilber/boot/file/entity/PartList.java @@ -0,0 +1,21 @@ +package com.zilber.boot.file.entity; + +import lombok.Data; + +import java.util.List; + +/** + * @Author LJX + * @TIME 2023-01-10 14:51 + * @PROJECT boot + * created by Intellij IDEA + * Description + */ +@Data +public class PartList { + + private Long total; + + private List tags; + +} diff --git a/src/main/java/com/zilber/boot/file/service/UploadUtils.java b/src/main/java/com/zilber/boot/file/service/UploadUtils.java index f45226c..082bee8 100644 --- a/src/main/java/com/zilber/boot/file/service/UploadUtils.java +++ b/src/main/java/com/zilber/boot/file/service/UploadUtils.java @@ -3,13 +3,14 @@ package com.zilber.boot.file.service; import com.aliyun.oss.*; import com.aliyun.oss.model.*; import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; -import com.cppcc.common.validator.ValidatorUtils; -import com.cppcc.files.*; -import com.cppcc.files.dao.FileDao; +import com.zilber.boot.file.dao.FileDao; import com.zilber.boot.file.entity.*; +import com.zilber.boot.utils.file.FileUtils; +import com.zilber.boot.utils.sign.Md5Utils; import lombok.extern.slf4j.Slf4j; import org.apache.commons.io.FilenameUtils; import org.apache.commons.lang3.StringUtils; +import org.apache.tomcat.util.security.MD5Encoder; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; @@ -33,7 +34,7 @@ import java.util.stream.Collectors; @Slf4j public class UploadUtils { - @Value("${cppcc.localtion}") + @Value("${zilber.localtion}") private String localtion; @Resource @@ -44,13 +45,20 @@ public class UploadUtils { public Map upload(MultipartFile file) { try { + Map objectMap = fileDao.listFileUrl(MD5Encoder.encode(file.getBytes()), 1); + if ( objectMap != null ){ + objectMap.put("name", file.getOriginalFilename()); + return objectMap; + } String type = "." + FilenameUtils.getExtension(file.getOriginalFilename()); String name = FilenameUtils.getName(file.getOriginalFilename()); String filePath = localtion + "/upload"; String fileName = UUID.randomUUID() + type; File desc = getAbsoluteFile(filePath, fileName); file.transferTo(desc); - return getPathFileName(filePath, fileName, name, type); + Map pathFileName = getPathFileName(filePath, fileName, name, type); + fileDao.addFile(MD5Encoder.encode(file.getBytes()), filePath, Integer.parseInt(pathFileName.get("type")), 1); + return pathFileName; } catch (Exception e) { log.error(e.getLocalizedMessage()); return new ConcurrentHashMap<>(); @@ -64,7 +72,7 @@ public class UploadUtils { String pathFileName = "/profile" + "/" + currentDir + "/" + fileName; map.put("url", pathFileName); map.put("name", name); - map.put("type", String.valueOf(SliceUploadsTemplate.getFileType(type))); + map.put("type", String.valueOf(getFileType(type))); return map; } @@ -86,7 +94,16 @@ public class UploadUtils { * @param module oss目录 * @return */ - public PutObjectResult upload(MultipartFile file, @Nullable String module) { + public Map upload(MultipartFile file, @Nullable String module) { + try { + Map objectMap = fileDao.listFileUrl(MD5Encoder.encode(file.getBytes()), 2); + if ( objectMap != null ){ + objectMap.put("name", file.getOriginalFilename()); + return objectMap; + } + } catch (IOException e) { + e.printStackTrace(); + } /** * 获取oss的属性 */ @@ -97,8 +114,9 @@ public class UploadUtils { if ( StringUtils.isBlank(module) ){ module = ossProperties.getModule(); } - String extension = file.getName().substring(file.getName().lastIndexOf(".")); + String extension = "." + FilenameUtils.getExtension(file.getOriginalFilename()); String objectName = module + "/" + UUID.randomUUID().toString() + extension; + Map resultMap = new HashMap<>(); // 创建OSSClient实例。 OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret); @@ -110,7 +128,15 @@ public class UploadUtils { putObjectRequest.setProcess("true"); // 上传字符串。 PutObjectResult result = ossClient.putObject(putObjectRequest); - return result; + if ( result.getResponse().getStatusCode() == 200 ){ + Integer fileType = getFileType(extension); + String uri = result.getResponse().getUri(); + resultMap.put("url", uri); + resultMap.put("name", file.getOriginalFilename()); + resultMap.put("type", String.valueOf(fileType)); + fileDao.addFile(MD5Encoder.encode(file.getBytes()), uri, fileType, 2); + return resultMap; + } } catch (OSSException oe) { throw new ServiceException(oe.getMessage()); } catch (ClientException ce) { @@ -145,7 +171,7 @@ public class UploadUtils { /********************************************************************************************/ - public FileUploadDTO sliceUploads(FileUploadsRequestDTO param) { + public ETag sliceUploads(FileUploadsRequestDTO param) { boolean isOk = true; File root = new File(localtion + "/upload", param.getUUID()); if (!root.exists() || !root.isDirectory()) { @@ -163,40 +189,98 @@ public class UploadUtils { map.put(param.getChunk(), param.getUUID()); if (isOk) { String sliceName = param.getChunk().toString(); - upload(root, sliceName, param); + return upload(root, sliceName, param); } - return FileUploadDTO.builder().chunkMd5Info(map).build(); + return null; } /** * 文件检测 - * + * { + * "requestId": "63BD04BA1253C53638A9F751", + * "bucketName": "zilber-public", + * "key": "upload/3a3cd46a-d966-4258-a6e7-a3b318cbe133.jpg", + * "uploadId": "70F44C7139E14DE0AB6BD7442F0F4AFE", + * "maxParts": 100, + * "partNumberMarker": 1, + * "storageClass": "Standard", + * "nextPartNumberMarker": 2, + * "parts": [ + * { + * "partNumber": 2, + * "lastModified": "2023-01-10T14:08:37.000+0800", + * "size": 566470, + * "etag": "21DE9DD8AE549FF2285DDC5E23B67867" + * } + * ], + * "truncated": false + * } * @param md5 md5 * @param UUID UUID * @return * @throws IOException */ - public FileCheckDTO fileCheck(String md5, String UUID) throws IOException { - FileCheckDTO fileCheckDTO = new FileCheckDTO(); - //根据文件md5查询文件是否存在,如果存在,则直接返回文件路径,否则返回块信息 - //TODO - Map objectMap = fileDao.listFileUrl(md5); - if (objectMap != null) { - fileCheckDTO.setUrl(objectMap.get("url").toString()); - fileCheckDTO.setType(Integer.parseInt(objectMap.get("type").toString())); - fileCheckDTO.setExist(true); - return fileCheckDTO; - } - //不存在 - return checkUnexist(UUID, fileCheckDTO); + public PartList fileCheck(String md5, String UUID) throws IOException { + PartList list = new PartList(); + List eTags = new ArrayList<>(); + File root = new File(localtion + "/upload", UUID); + if (!root.exists()) { + return null; + } + //获取总块数 +// File aConf = new File(root.getAbsolutePath(), UUID + ".conf"); +// FileReader fr = new FileReader(aConf); +// char[] chunkCs = new char[(int) aConf.length()]; +// fr.read(chunkCs); + Long chunks = chunks(root, UUID); + list.setTotal(chunks); + FilenameFilter filter = new FilenameFilter() { + @Override + public boolean accept(File file, String s) { + return s.endsWith(".conf") && !s.contains("-"); + } + }; + String[] fileNames = root.list(filter); + if (fileNames == null) { + return null; + } + List fileNameList = Arrays.asList(fileNames) + .stream().distinct().collect(Collectors.toList()); + if (CollectionUtils.isNotEmpty(fileNameList)) { + for (String fileName : fileNameList) { + String prefix = fileName.split("\\.")[0]; + ETag tag = new ETag(); + tag.setPartSize(new File(root.getAbsolutePath(), fileName).getTotalSpace()); + tag.setPartNumber(Integer.parseInt(prefix)); + eTags.add(tag); + } + list.setTags(eTags); + return list; + } + return list; } /** + * { + * "partNumber": 2, + * "partSize": 566470, + * "partCRC": 997575365254752264, + * "etag": "21DE9DD8AE549FF2285DDC5E23B67867" + * } * @return * @author liuao */ - public boolean upload(File root, String name, FileUploadsRequestDTO param) { + public ETag upload(File root, String name, FileUploadsRequestDTO param) { + //保存最大块数 + ETag tag = new ETag(); + try { + tag.setPartNumber(param.getChunk().intValue()); + tag.setPartSize(param.getChunkSize()); + tag.setETag(MD5Encoder.encode(param.getFile().getBytes())); + } catch (IOException e) { + e.printStackTrace(); + } File aConfFile = new File(root.getAbsolutePath(), param.getUUID() + ".conf"); File sizeFile = new File(root.getAbsolutePath(), "size.conf"); if (!aConfFile.exists()) { @@ -229,7 +313,7 @@ public class UploadUtils { accessTmpFile = new RandomAccessFile(tmpFile, "rw"); accessTmpFile.write(param.getFile().getBytes()); log.info(param.getUUID() + "文件块" + param.getChunk() + "上传完成"); - return true; + return tag; } catch (IOException e) { log.error(e.getMessage(), e); if (tmpConfFile.exists()) { @@ -251,28 +335,40 @@ public class UploadUtils { } } } - return false; + return null; } - public FileCheckDTO compose(String UUID, String type, String md5) { + /** + * { + * "requestId": "63BD05267FFDC23733FE3B95", + * "clientCRC": -1453100417491105764, + * "serverCRC": -1453100417491105764, + * "bucketName": "zilber-public", + * "key": "upload/3a3cd46a-d966-4258-a6e7-a3b318cbe133.jpg", + * "location": "http://zilber-public.oss-cn-beijing.aliyuncs.com/upload/3a3cd46a-d966-4258-a6e7-a3b318cbe133.jpg", + * "etag": "8DDB27878F7D65485F8E83A2B5E7F11E-2" + * } + * @param UUID + * @param type + * @param md5 + * @return + */ + public Complete compose(String UUID, String type, String md5) { long startTime = 0, endTime = 0; log.info(String.valueOf(System.currentTimeMillis())); - FileCheckDTO fileCheckDTO = new FileCheckDTO(); + Complete complete = new Complete(); File root = new File(localtion + "/upload", UUID); File targetFile = new File(localtion + "/upload", UUID + type); Long chunks = chunks(root, UUID); File[] fileNames = root.listFiles((file1, s1) -> !s1.endsWith(".conf")); if (fileNames == null || fileNames.length < chunks) { - return checkUnexist(UUID, new FileCheckDTO()); + return null; } List collect = Arrays.asList(fileNames) - .stream().sorted(new Comparator() { - @Override - public int compare(File file, File t1) { - int f = Integer.parseInt(file.getName()); - int t = Integer.parseInt(t1.getName()); - return f < t ? -1 : 1; - } + .stream().sorted((file, t1) -> { + int f = Integer.parseInt(file.getName()); + int t = Integer.parseInt(t1.getName()); + return f < t ? -1 : 1; }).collect(Collectors.toList()); FileOutputStream fos; FileInputStream fis; @@ -304,54 +400,11 @@ public class UploadUtils { String currentDir = StringUtils.substring(localtion + "/upload", dirLastIndex); String pathFileName = "/profile" + "/" + currentDir + "/" + UUID + type; Integer t = getFileType(type); - fileDao.addFile(md5, pathFileName, t); - fileCheckDTO.setUrl(pathFileName); - fileCheckDTO.setType(t); - fileCheckDTO.setExist(true); + fileDao.addFile(md5, pathFileName, t, 1); + complete.setLocation(pathFileName); + complete.setType(t); clearTempFiles(root); - return fileCheckDTO; - } - - private FileCheckDTO checkUnexist(String UUID, FileCheckDTO fileCheckDTO) { - //不存在 - fileCheckDTO.setExist(false); - File root = new File(localtion + "/upload", UUID); - if (!root.exists()) { - fileCheckDTO.setUploaded(false); - return fileCheckDTO; - } - //获取总块数 -// File aConf = new File(root.getAbsolutePath(), UUID + ".conf"); -// FileReader fr = new FileReader(aConf); -// char[] chunkCs = new char[(int) aConf.length()]; -// fr.read(chunkCs); - Long chunks = chunks(root, UUID); - FilenameFilter filter = new FilenameFilter() { - @Override - public boolean accept(File file, String s) { - return s.endsWith(".conf") && !s.contains("-"); - } - }; - String[] fileNames = root.list(filter); - if (fileNames == null) { - fileCheckDTO.setUploaded(false); - return fileCheckDTO; - } - List fileNameList = Arrays.asList(fileNames) - .stream().distinct().collect(Collectors.toList()); - Map chunkInfo = new HashMap<>(); - if (CollectionUtils.isNotEmpty(fileNameList)) { - for (String fileName : fileNameList) { - String prefix = fileName.split("\\.")[0]; - chunkInfo.put(prefix, true); - } - fileCheckDTO.setChunkInfo(chunkInfo); - fileCheckDTO.setUploaded(true); - fileCheckDTO.setChunks(chunks); - return fileCheckDTO; - } - fileCheckDTO.setUploaded(false); - return fileCheckDTO; + return complete; } private Long chunks(File root, String UUID) { @@ -396,7 +449,7 @@ public class UploadUtils { * @param module 目标文件夹 * @return 文件唯一标识 */ - public OssPartUpload InitiateMultipartUpload(String fileName, @Nullable String module, OssProperties provided) { + public OssPartUpload InitiateMultipartUpload(String fileName, @Nullable String module,@Nullable OssProperties provided) { /** * 获取oss的属性 */ @@ -404,30 +457,38 @@ public class UploadUtils { String accessKeyId = ""; String accessKeySecret = ""; String bucketName = ""; - if ( StringUtils.isNotBlank(provided.getEndpoint())){ - endpoint = provided.getEndpoint(); + if ( provided != null ){ + if ( StringUtils.isNotBlank(provided.getEndpoint())){ + endpoint = provided.getEndpoint(); + }else { + endpoint = ossProperties.getEndpoint(); + } + if ( StringUtils.isNotBlank(provided.getKeyId())){ + accessKeyId = provided.getKeyId(); + }else { + accessKeyId = ossProperties.getKeyId(); + } + if ( StringUtils.isNotBlank(provided.getKeySecret())){ + accessKeySecret = provided.getKeySecret(); + }else { + accessKeySecret = ossProperties.getKeySecret(); + } + if ( StringUtils.isNotBlank(provided.getBucketName())){ + bucketName = provided.getBucketName(); + }else { + bucketName = ossProperties.getBucketName(); + } }else { endpoint = ossProperties.getEndpoint(); - } - if ( StringUtils.isNotBlank(provided.getKeyId())){ - accessKeyId = provided.getKeyId(); - }else { accessKeyId = ossProperties.getKeyId(); - } - if ( StringUtils.isNotBlank(provided.getKeySecret())){ - accessKeySecret = provided.getKeySecret(); - }else { accessKeySecret = ossProperties.getKeySecret(); - } - if ( StringUtils.isNotBlank(provided.getBucketName())){ - bucketName = provided.getBucketName(); - }else { bucketName = ossProperties.getBucketName(); } + if ( StringUtils.isBlank(module) ){ module = ossProperties.getModule(); } - String extension = fileName.substring(fileName.lastIndexOf(".")); + String extension = "." + FilenameUtils.getExtension(fileName); String objectName = module + "/" + UUID.randomUUID().toString() + extension; Map resultMap = new HashMap<>(); @@ -449,8 +510,8 @@ public class UploadUtils { * @param upload 分片信息 * @return */ - public UploadPartResult uploadPart(OssPartUpload upload) { - ValidatorUtils.validateEntity(upload, DefaultGroup.class); + public PartETag uploadPart(OssPartUpload upload) { + //ValidatorUtils.validateEntity(upload); /** * 获取oss的属性 */ @@ -493,7 +554,7 @@ public class UploadUtils { // 设置分片号。每一个上传的分片都有一个分片号,取值范围是1~10000,如果超出此范围,OSS将返回InvalidArgument错误码。 uploadPartRequest.setPartNumber(upload.getPartNumber()); // 每个分片不需要按顺序上传,甚至可以在不同客户端上传,OSS会按照分片号排序组成完整的文件。 - return ossClient.uploadPart(uploadPartRequest); + return ossClient.uploadPart(uploadPartRequest).getPartETag(); } catch (IOException e) { e.printStackTrace(); } @@ -506,7 +567,7 @@ public class UploadUtils { * @return */ public PartListing list(OssListParts parts) { - ValidatorUtils.validateEntity(parts, DefaultGroup.class); + //ValidatorUtils.validateEntity(parts); /** * 获取oss的属性 */ @@ -558,7 +619,7 @@ public class UploadUtils { * @return */ public CompleteMultipartUploadResult completeUpload(OssComplete complete) { - ValidatorUtils.validateEntity(complete, DefaultGroup.class); + //ValidatorUtils.validateEntity(complete, DefaultGroup.class); /** * 获取oss的属性 */ @@ -586,7 +647,13 @@ public class UploadUtils { }else { bucketName = ossProperties.getBucketName(); } - + List partETags = new ArrayList<>(); + if ( CollectionUtils.isNotEmpty(complete.getTags())){ + for ( ETag e : complete.getTags()){ + PartETag partETag = new PartETag(e.getPartNumber(), e.getETag(), e.getPartSize(), e.getPartCRC()); + partETags.add(partETag); + } + } // 创建OSSClient实例。 OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret); // 在执行完成分片上传操作时,需要提供所有有效的partETags。OSS收到提交的partETags后,会逐一验证每个分片的有效性。当所有的数据分片验证通过后,OSS将把这些分片组合成一个完整的文件。 @@ -594,7 +661,7 @@ public class UploadUtils { new CompleteMultipartUploadRequest(bucketName, complete.getKey(), complete.getUploadId(), - complete.getTags()); + partETags); // 完成分片上传。 return ossClient.completeMultipartUpload(completeMultipartUploadRequest); } @@ -604,7 +671,7 @@ public class UploadUtils { * @param cancel */ public void abortUpload(OssCancel cancel) { - ValidatorUtils.validateEntity(cancel, DefaultGroup.class); + //ValidatorUtils.validateEntity(cancel, DefaultGroup.class); /** * 获取oss的属性 */ diff --git a/src/main/java/com/zilber/boot/utils/Base64Util.java b/src/main/java/com/zilber/boot/utils/Base64Util.java index 5edcd61..f2ab348 100644 --- a/src/main/java/com/zilber/boot/utils/Base64Util.java +++ b/src/main/java/com/zilber/boot/utils/Base64Util.java @@ -1,79 +1,79 @@ -package com.zilber.boot.utils; - -import sun.misc.BASE64Decoder; -import sun.misc.BASE64Encoder; - -import javax.imageio.stream.FileImageInputStream; -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.IOException; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -public class Base64Util{ - /** - * 字符串转图片 - * @param base64Str - * @return - */ - public static byte[] decode(String base64Str){ - byte[] b = null; - BASE64Decoder decoder = new BASE64Decoder(); - try { - b = decoder.decodeBuffer(replaceEnter(base64Str)); - } catch (IOException e) { - e.printStackTrace(); - } - return b; - } - - /** - * 图片转字符串 - * @param image - * @return - */ - public static String encode(byte[] image){ - BASE64Encoder decoder = new BASE64Encoder(); - return replaceEnter(decoder.encode(image)); - } - - public static String encode(String uri){ - BASE64Encoder encoder = new BASE64Encoder(); - return replaceEnter(encoder.encode(uri.getBytes())); - } - - /** - * - * @path 图片路径 - * @return - */ - - public static byte[] imageTobyte(String path){ - byte[] data = null; - FileImageInputStream input = null; - try { - input = new FileImageInputStream(new File(path)); - ByteArrayOutputStream output = new ByteArrayOutputStream(); - byte[] buf = new byte[1024]; - int numBytesRead = 0; - while((numBytesRead = input.read(buf)) != -1){ - output.write(buf, 0, numBytesRead); - } - data = output.toByteArray(); - output.close(); - input.close(); - - } catch (Exception e) { - e.printStackTrace(); - } - - return data; - } - - public static String replaceEnter(String str){ - String reg ="[\n-\r]"; - Pattern p = Pattern.compile(reg); - Matcher m = p.matcher(str); - return m.replaceAll(""); - } -} \ No newline at end of file +//package com.zilber.boot.utils; +// +//import sun.misc.BASE64Decoder; +//import sun.misc.BASE64Encoder; +// +//import javax.imageio.stream.FileImageInputStream; +//import java.io.ByteArrayOutputStream; +//import java.io.File; +//import java.io.IOException; +//import java.util.regex.Matcher; +//import java.util.regex.Pattern; +// +//public class Base64Util{ +// /** +// * 字符串转图片 +// * @param base64Str +// * @return +// */ +// public static byte[] decode(String base64Str){ +// byte[] b = null; +// BASE64Decoder decoder = new BASE64Decoder(); +// try { +// b = decoder.decodeBuffer(replaceEnter(base64Str)); +// } catch (IOException e) { +// e.printStackTrace(); +// } +// return b; +// } +// +// /** +// * 图片转字符串 +// * @param image +// * @return +// */ +// public static String encode(byte[] image){ +// BASE64Encoder decoder = new BASE64Encoder(); +// return replaceEnter(decoder.encode(image)); +// } +// +// public static String encode(String uri){ +// BASE64Encoder encoder = new BASE64Encoder(); +// return replaceEnter(encoder.encode(uri.getBytes())); +// } +// +// /** +// * +// * @path 图片路径 +// * @return +// */ +// +// public static byte[] imageTobyte(String path){ +// byte[] data = null; +// FileImageInputStream input = null; +// try { +// input = new FileImageInputStream(new File(path)); +// ByteArrayOutputStream output = new ByteArrayOutputStream(); +// byte[] buf = new byte[1024]; +// int numBytesRead = 0; +// while((numBytesRead = input.read(buf)) != -1){ +// output.write(buf, 0, numBytesRead); +// } +// data = output.toByteArray(); +// output.close(); +// input.close(); +// +// } catch (Exception e) { +// e.printStackTrace(); +// } +// +// return data; +// } +// +// public static String replaceEnter(String str){ +// String reg ="[\n-\r]"; +// Pattern p = Pattern.compile(reg); +// Matcher m = p.matcher(str); +// return m.replaceAll(""); +// } +//} \ No newline at end of file diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 6f8df71..ed60afb 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -16,7 +16,7 @@ zilberboot: # 开发环境配置 server: # 服务器的HTTP端口,默认为8080 - port: 8080 + port: 8081 servlet: # 应用的访问路径 context-path: / @@ -153,3 +153,14 @@ xss: excludes: /system/notice # 匹配链接 urlPatterns: /system/*,/monitor/*,/tool/* + +zilber: + localtion: D:/ + +aliyun: + oss: + endpoint: oss-cn-beijing.aliyuncs.com + keyId: LTAI5t8p8JcfHgs1xsHDhbTS + keySecret: a2NgvAo2EXy4UbUTQm3xtirHSQbPiO + bucketName: zilber-public + module: upload