Merge branch 'master' into feature/icon_management
# Conflicts: # oss-common/src/main/java/cn/axzo/oss/common/enums/CodeEnum.java
This commit is contained in:
commit
53c44e0342
@ -7,22 +7,17 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.cloud.openfeign.EnableFeignClients;
|
||||
|
||||
/**
|
||||
* OSS 启动类
|
||||
*
|
||||
* @author zhaoyong
|
||||
* @see Bootstrap
|
||||
* @since 2021-07-15 11:34
|
||||
*/
|
||||
* @author hucf
|
||||
* @since 2024/1/16 15:11
|
||||
**/
|
||||
@Slf4j
|
||||
@MapperScan(basePackages = {"cn.axzo.oss.dal.mapper", "cn.axzo.oss.client.icon.mapper"})
|
||||
@EnableFeignClients(basePackages = {"cn.axzo.log.platform.client"})
|
||||
@SpringBootApplication(scanBasePackages = {"cn.axzo.oss"})
|
||||
public class Bootstrap {
|
||||
|
||||
public static void main(String[] args) {
|
||||
log.info("axzo oss begin starting...");
|
||||
SpringApplication.run(Bootstrap.class, args);
|
||||
log.info("axzo oss start success");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -8,16 +8,22 @@ import cn.axzo.oss.http.model.*;
|
||||
import cn.axzo.oss.manager.api.dto.request.FindFileKeyDto;
|
||||
import cn.axzo.oss.manager.api.dto.request.FindFileUrlDto;
|
||||
import cn.axzo.oss.manager.api.dto.request.ServerFileDeleteDto;
|
||||
import cn.axzo.oss.manager.api.dto.request.ServerFileDownloadDto;
|
||||
import cn.axzo.oss.manager.api.dto.request.ServerFileUploadDto;
|
||||
import cn.axzo.oss.manager.api.dto.response.ServerFileDownloadResponse;
|
||||
import cn.axzo.oss.service.api.FileService;
|
||||
import cn.azxo.framework.common.model.CommonResponse;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import feign.Response;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.validation.Valid;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
|
||||
@ -5,13 +5,21 @@ import cn.axzo.framework.auth.annotation.PreBuildContext;
|
||||
import cn.axzo.framework.auth.domain.ContextInfo;
|
||||
import cn.axzo.framework.auth.domain.ContextInfoHolder;
|
||||
import cn.axzo.oss.client.vo.*;
|
||||
import cn.axzo.oss.common.enums.ChannelTypeEnum;
|
||||
import cn.axzo.oss.common.enums.FileDownloadTypeEnum;
|
||||
import cn.axzo.oss.common.enums.FileUploadTypeEnum;
|
||||
import cn.axzo.oss.common.enums.StorageUnitEnum;
|
||||
import cn.axzo.oss.common.exception.BizException;
|
||||
import cn.axzo.oss.common.utils.BeanConvertUtil;
|
||||
import cn.axzo.oss.http.model.TemporaryUrlAccessRes;
|
||||
import cn.axzo.oss.http.model.WebFileUploadVo;
|
||||
import cn.axzo.oss.manager.api.dto.request.*;
|
||||
import cn.axzo.oss.manager.api.dto.response.*;
|
||||
import cn.axzo.oss.service.api.FileService;
|
||||
import cn.azxo.framework.common.model.CommonResponse;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
@ -19,8 +27,7 @@ import org.springframework.web.multipart.MultipartFile;
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.validation.Valid;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.*;
|
||||
import java.util.List;
|
||||
|
||||
import static cn.axzo.oss.common.enums.CodeEnum.FILE_NAME_TOO_LONG;
|
||||
@ -34,6 +41,7 @@ import static org.springframework.http.MediaType.MULTIPART_FORM_DATA_VALUE;
|
||||
**/
|
||||
@RestController
|
||||
@RequestMapping("/webApi")
|
||||
@Slf4j
|
||||
public class WebFileController {
|
||||
|
||||
private static int FILE_NAME_MAX_LENGTH = 128;
|
||||
@ -95,8 +103,9 @@ public class WebFileController {
|
||||
@SneakyThrows
|
||||
@PostMapping("/v1/multipart-upload/init")
|
||||
@CrossOrigin
|
||||
public CommonResponse<MultipartUploadInitVo> multipartUploadInit(@Valid @RequestBody MultipartUploadInitDto dto) {
|
||||
MultipartUploadInitResponse response = fileService.multipartUploadInit(dto);
|
||||
public CommonResponse<MultipartUploadInitVo> multipartUploadInit(@Valid @RequestBody MultipartUploadInitDto dto,
|
||||
Integer fileUploadType) {
|
||||
MultipartUploadInitResponse response = fileService.multipartUploadInit(dto, fileUploadType);
|
||||
return CommonResponse.success(BeanConvertUtil.copyBean(response, MultipartUploadInitVo.class));
|
||||
}
|
||||
|
||||
@ -121,7 +130,7 @@ public class WebFileController {
|
||||
.partSize(partSize)
|
||||
.uploadId(uploadId)
|
||||
.build();
|
||||
MultipartUploadResponse response = fileService.multipartUpload(dto);
|
||||
MultipartUploadResponse response = fileService.multipartUpload(dto, ChannelTypeEnum.OSS.getCode());
|
||||
return CommonResponse.success(BeanConvertUtil.copyBean(response, MultipartUploadVo.class));
|
||||
}
|
||||
|
||||
@ -138,7 +147,7 @@ public class WebFileController {
|
||||
.fileName(fileName)
|
||||
.file(file)
|
||||
.build();
|
||||
FileInformationResponse response = fileService.multipartUploadFile(dto);
|
||||
FileInformationResponse response = fileService.multipartUploadFile(dto, ChannelTypeEnum.OSS.getCode());
|
||||
return CommonResponse.success(BeanConvertUtil.copyBean(response, FileInformationVo.class));
|
||||
}
|
||||
|
||||
@ -147,7 +156,7 @@ public class WebFileController {
|
||||
@SneakyThrows
|
||||
//@PreBuildContext
|
||||
public CommonResponse<FileInformationVo> multipartUploadComplete(@Valid @RequestBody MultipartUploadCompleteDto dto) {
|
||||
FileInformationResponse response = fileService.multipartUploadComplete(dto);
|
||||
FileInformationResponse response = fileService.multipartUploadComplete(dto, ChannelTypeEnum.OSS.getCode());
|
||||
return CommonResponse.success(BeanConvertUtil.copyBean(response, FileInformationVo.class));
|
||||
}
|
||||
|
||||
@ -180,4 +189,167 @@ public class WebFileController {
|
||||
outputStream.close();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* OBS:文件上传(断点续传)
|
||||
*
|
||||
* @param appCode 应用编码
|
||||
* @param bizScene 业务场景
|
||||
* @param file MultipartFile
|
||||
* @return WebFileUploadVo
|
||||
*/
|
||||
@SneakyThrows
|
||||
@PostMapping(value = "/v1/file2", consumes = MULTIPART_FORM_DATA_VALUE)
|
||||
@CrossOrigin
|
||||
public CommonResponse<WebFileUploadVo> uploadObs(@Valid @RequestParam("appCode") String appCode,
|
||||
@Valid @RequestParam("bizScene") String bizScene,
|
||||
@Valid @RequestPart MultipartFile file) {
|
||||
// 获取用户信息
|
||||
ContextInfo.LiteSaasContext liteSaasContext = null;
|
||||
ContextInfo contextInfo = ContextInfoHolder.get();
|
||||
if (contextInfo != null) {
|
||||
liteSaasContext = contextInfo.lite();
|
||||
}
|
||||
|
||||
// 文件大于100k,生成临时文件,进行断点续传
|
||||
int checkPointLengthLimit = StorageUnitEnum.KB.getSize() * 100;
|
||||
byte[] fileContent = file.getBytes();
|
||||
int fileLength = fileContent.length;
|
||||
String filePath = null;
|
||||
if (fileLength > checkPointLengthLimit) {
|
||||
filePath = fileService.getFilePath(file);
|
||||
}
|
||||
|
||||
String filename = file.getOriginalFilename();
|
||||
BizException.error(filename.length() < FILE_NAME_MAX_LENGTH, FILE_NAME_TOO_LONG);
|
||||
ServerFileUploadDto fileUploadDto = ServerFileUploadDto.builder()
|
||||
.appCode(appCode)
|
||||
.bizScene(bizScene)
|
||||
.fileName(filename)
|
||||
.fileContent(fileContent)
|
||||
.filePath(filePath)
|
||||
.build();
|
||||
ServerFileUploadResponse response = fileService.uploadObs(fileUploadDto, liteSaasContext,
|
||||
FileUploadTypeEnum.CHECK_POINT.getCode());
|
||||
WebFileUploadVo result = BeanConvertUtil.copyBean(response, WebFileUploadVo.class);
|
||||
return CommonResponse.success(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* OBS:分段上传
|
||||
*
|
||||
* @param appCode 应用编码
|
||||
* @param bizScene 业务场景
|
||||
* @param file MultipartFile
|
||||
* @return WebFileUploadVo
|
||||
*/
|
||||
@SneakyThrows
|
||||
@PostMapping(value = "/v1/partUpload", consumes = MULTIPART_FORM_DATA_VALUE)
|
||||
@CrossOrigin
|
||||
public CommonResponse<WebFileUploadVo> partUpload(@Valid @RequestParam("appCode") String appCode,
|
||||
@Valid @RequestParam("bizScene") String bizScene,
|
||||
@Valid @RequestPart MultipartFile file) {
|
||||
// 获取用户信息
|
||||
ContextInfo.LiteSaasContext liteSaasContext = null;
|
||||
ContextInfo contextInfo = ContextInfoHolder.get();
|
||||
if (contextInfo != null) {
|
||||
liteSaasContext = contextInfo.lite();
|
||||
}
|
||||
String filename = file.getOriginalFilename();
|
||||
BizException.error(filename.length() < FILE_NAME_MAX_LENGTH, FILE_NAME_TOO_LONG);
|
||||
ServerFileUploadDto fileUploadDto = ServerFileUploadDto.builder()
|
||||
.appCode(appCode)
|
||||
.bizScene(bizScene)
|
||||
.fileName(filename)
|
||||
.fileContent(file.getBytes())
|
||||
.build();
|
||||
ServerFileUploadResponse response = fileService.uploadObs(fileUploadDto, liteSaasContext,
|
||||
FileUploadTypeEnum.MULTI_PART_UPLOAD.getCode());
|
||||
WebFileUploadVo result = BeanConvertUtil.copyBean(response, WebFileUploadVo.class);
|
||||
return CommonResponse.success(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* obs:流式下载
|
||||
*
|
||||
* @param dto ServerFileDownloadDto
|
||||
* @param response HttpServletResponse
|
||||
*/
|
||||
@SneakyThrows
|
||||
@GetMapping("/v1/obs/getObject")
|
||||
@CrossOrigin
|
||||
public void getObject(@Valid ServerFileDownloadDto dto, HttpServletResponse response) {
|
||||
ServerFileDownloadResponse result = fileService.getObject(dto, FileDownloadTypeEnum.STREAM_DOWNLOAD.getCode());
|
||||
try (OutputStream outputStream = response.getOutputStream(); InputStream inputStream = result.getFileStream()) {
|
||||
response.setContentType("image/jpg");
|
||||
response.setCharacterEncoding("UTF-8");
|
||||
response.addHeader("Content-Disposition", "attachment;filename="
|
||||
+ result.getFileName() + "." + result.getFileFormat());
|
||||
IOUtils.copy(inputStream, outputStream);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* obs:断点续传下载
|
||||
*
|
||||
* @param dto ServerFileDownloadDto
|
||||
* @param response HttpServletResponse
|
||||
*/
|
||||
@SneakyThrows
|
||||
@GetMapping("/v1/obs/downloadFile")
|
||||
@CrossOrigin
|
||||
public void downloadFile(@Valid ServerFileDownloadDto dto, HttpServletResponse response) {
|
||||
ServerFileDownloadResponse result = fileService.getObject(dto, FileDownloadTypeEnum.CHECK_POINT_DOWNLOAD.getCode());
|
||||
try (OutputStream outputStream = response.getOutputStream(); InputStream inputStream = result.getFileStream()) {
|
||||
response.setContentType("image/jpg");
|
||||
response.setCharacterEncoding("UTF-8");
|
||||
response.addHeader("Content-Disposition", "attachment;filename="
|
||||
+ result.getFileName() + "." + result.getFileFormat());
|
||||
IOUtils.copy(inputStream, outputStream);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 远程下载接口
|
||||
*
|
||||
* @param fileUuId 文件uuid
|
||||
* @param response HttpServletResponse
|
||||
*/
|
||||
@GetMapping("/v1/obs/downloadFileFromObs")
|
||||
public void downloadFileFromObs(@RequestParam("fileUuid") String fileUuId, HttpServletResponse response) {
|
||||
ServerFileDownloadDto dto = new ServerFileDownloadDto();
|
||||
dto.setFileKey(fileUuId);
|
||||
ServerFileDownloadResponse result = fileService.getObject(dto, FileDownloadTypeEnum.STREAM_DOWNLOAD.getCode());
|
||||
|
||||
try (OutputStream outputStream = response.getOutputStream(); InputStream inputStream = result.getFileStream()) {
|
||||
response.setHeader("content-type","application/octet-stream");
|
||||
response.setContentType("application/octet-stream");
|
||||
response.setCharacterEncoding("UTF-8");
|
||||
response.addHeader("Content-Disposition", "attachment;filename=" + result.getFileName() + "." + result.getFileFormat());
|
||||
IOUtils.copy(inputStream, outputStream);
|
||||
log.info("response设置文件流成功");
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过临时url访问OBS
|
||||
*
|
||||
* @param fileUuId 文件uuid
|
||||
* @return TemporaryUrlAccessRes
|
||||
*/
|
||||
@GetMapping("/v1/obs/temporaryUrlAccess")
|
||||
public CommonResponse<TemporaryUrlAccessRes> temporaryUrlAccess(@RequestParam("fileUuid") String fileUuId) {
|
||||
ServerFileDownloadDto dto = new ServerFileDownloadDto();
|
||||
dto.setFileKey(fileUuId);
|
||||
ServerFileDownloadResponse response = fileService.getObject(dto, FileDownloadTypeEnum.TEMPORARY_URL_ACCESS.getCode());
|
||||
TemporaryUrlAccessRes result = BeanConvertUtil.copyBean(response, TemporaryUrlAccessRes.class);
|
||||
log.info("下载结果, result = {}", JSONUtil.toJsonStr(result));
|
||||
return CommonResponse.success(result);
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,39 @@
|
||||
package cn.axzo.oss.common.enums;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* 渠道类型枚举类
|
||||
*
|
||||
* @author hucf
|
||||
* @since 2024/1/15 10:15
|
||||
**/
|
||||
@Getter
|
||||
public enum ChannelTypeEnum {
|
||||
OSS(1, "阿里云", "aliyun"),
|
||||
OBS(2, "华为云", "huaweicloud"),
|
||||
;
|
||||
|
||||
private final Integer code;
|
||||
|
||||
private final String message;
|
||||
|
||||
private final String channelCode;
|
||||
|
||||
ChannelTypeEnum(Integer code, String message, String channelCode) {
|
||||
this.code = code;
|
||||
this.message = message;
|
||||
this.channelCode = channelCode;
|
||||
}
|
||||
|
||||
public static String getChannelCodeByCode(Integer code) {
|
||||
String channelCode = null;
|
||||
for (ChannelTypeEnum value : ChannelTypeEnum.values()) {
|
||||
if (value.getCode().equals(code)) {
|
||||
channelCode = value.getChannelCode();
|
||||
break;
|
||||
}
|
||||
}
|
||||
return channelCode;
|
||||
}
|
||||
}
|
||||
@ -48,10 +48,12 @@ public enum CodeEnum implements EnumBase<Integer> {
|
||||
MULTIPART_UPLOAD_ERROR(114, "文件上传失败"),
|
||||
MULTIPART_UPLOAD_COMPLETE_ERROR(115, "文件上传失败"),
|
||||
|
||||
ICON_GROUP_EXIST(116, "图标组已存在"),
|
||||
ICON_GROUP_NOT_EXIST(117, "图标组不存在"),
|
||||
ICON_EXIST(118, "图标已存在"),
|
||||
FILE_FORMAT_MAY_ERROR(119, "文件格式可能错误")
|
||||
OBS_CLIENT_NULL(116,"obs client为空"),
|
||||
|
||||
ICON_GROUP_EXIST(117, "图标组已存在"),
|
||||
ICON_GROUP_NOT_EXIST(118, "图标组不存在"),
|
||||
ICON_EXIST(119, "图标已存在"),
|
||||
FILE_FORMAT_MAY_ERROR(201, "文件格式可能错误")
|
||||
|
||||
|
||||
;
|
||||
|
||||
@ -0,0 +1,24 @@
|
||||
package cn.axzo.oss.common.enums;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* 文件下载类型枚举类
|
||||
*
|
||||
* @author hucf
|
||||
* @since 2024/1/23 17:57
|
||||
**/
|
||||
@Getter
|
||||
public enum FileDownloadTypeEnum {
|
||||
STREAM_DOWNLOAD(1, "流式下载"),
|
||||
CHECK_POINT_DOWNLOAD(2, "断点续传下载"),
|
||||
TEMPORARY_URL_ACCESS(3, "通过临时url访问OBs")
|
||||
;
|
||||
private final Integer code;
|
||||
private final String message;
|
||||
|
||||
FileDownloadTypeEnum(Integer code, String message) {
|
||||
this.code = code;
|
||||
this.message = message;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,25 @@
|
||||
package cn.axzo.oss.common.enums;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* 文件上传方式枚举类
|
||||
*
|
||||
* @author hucf
|
||||
* @since 2024/1/15 16:43
|
||||
**/
|
||||
@Getter
|
||||
public enum FileUploadTypeEnum {
|
||||
DEFAULT_UPLOAD(1, "默认"),
|
||||
CHECK_POINT(2, "断点续传"),
|
||||
MULTI_PART_UPLOAD(3, "分段上传")
|
||||
;
|
||||
private final Integer code;
|
||||
|
||||
private final String message;
|
||||
|
||||
FileUploadTypeEnum(Integer code, String message) {
|
||||
this.code = code;
|
||||
this.message = message;
|
||||
}
|
||||
}
|
||||
@ -20,5 +20,5 @@ public interface AppChannelBucketDao extends IService<AppChannelBucket> {
|
||||
* @param appCode appcode
|
||||
* @return
|
||||
*/
|
||||
List<AppChannelBucket> getByAppCode(String appCode);
|
||||
List<AppChannelBucket> getByAppCode(String appCode, Integer fileUploadType);
|
||||
}
|
||||
|
||||
@ -1,11 +1,14 @@
|
||||
package cn.axzo.oss.dal.repository.impl;
|
||||
|
||||
import cn.axzo.oss.common.enums.ChannelTypeEnum;
|
||||
import cn.axzo.oss.common.enums.IsDeleteEnum;
|
||||
import cn.axzo.oss.dal.entity.AppChannelBucket;
|
||||
import cn.axzo.oss.dal.mapper.AppChannelBucketMapper;
|
||||
import cn.axzo.oss.dal.repository.AppChannelBucketDao;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
/**
|
||||
@ -27,8 +30,10 @@ public class AppChannelBucketDaoImpl extends
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public List<AppChannelBucket> getByAppCode(String appCode) {
|
||||
public List<AppChannelBucket> getByAppCode(String appCode, Integer channelType) {
|
||||
String channelCodeByCode = ChannelTypeEnum.getChannelCodeByCode(channelType);
|
||||
return lambdaQuery().eq(AppChannelBucket::getAppCode, appCode)
|
||||
.eq(Objects.nonNull(channelCodeByCode), AppChannelBucket::getChannelCode, channelCodeByCode)
|
||||
.eq(AppChannelBucket::getIsDelete, IsDeleteEnum.NO.getCode()).list();
|
||||
}
|
||||
}
|
||||
|
||||
@ -35,6 +35,10 @@
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-openfeign-core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-openfeign</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
|
||||
@ -0,0 +1,24 @@
|
||||
package cn.axzo.oss.http.api;
|
||||
|
||||
import cn.axzo.oss.http.model.TemporaryUrlAccessRes;
|
||||
import cn.azxo.framework.common.model.CommonResponse;
|
||||
import feign.Response;
|
||||
import org.springframework.cloud.openfeign.FeignClient;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
|
||||
/**
|
||||
* @author axzo
|
||||
* @since 2024/3/7 16:56
|
||||
**/
|
||||
@FeignClient(
|
||||
name = "oss",
|
||||
url = "http://oss:9123"
|
||||
)
|
||||
public interface DownloadFileApi {
|
||||
@GetMapping(value = "/webApi/v1/obs/downloadFileFromObs")
|
||||
CommonResponse<Response> downloadFileFromObs(@RequestParam("fileUuid") String fileUuId);
|
||||
|
||||
@GetMapping(value = "/webApi/v1/obs/temporaryUrlAccess")
|
||||
CommonResponse<TemporaryUrlAccessRes> temporaryUrlAccess(@RequestParam("fileUuid") String fileUuId);
|
||||
}
|
||||
@ -3,9 +3,13 @@ package cn.axzo.oss.http.api;
|
||||
import cn.axzo.oss.http.model.*;
|
||||
import cn.azxo.framework.common.model.CommonResponse;
|
||||
import org.springframework.cloud.openfeign.FeignClient;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
|
||||
import feign.Response;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
|
||||
@ -0,0 +1,38 @@
|
||||
package cn.axzo.oss.http.api;
|
||||
|
||||
import cn.axzo.oss.http.model.WebFileUploadVo;
|
||||
import cn.azxo.framework.common.model.CommonResponse;
|
||||
import feign.Response;
|
||||
import org.springframework.cloud.openfeign.FeignClient;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RequestPart;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.validation.Valid;
|
||||
|
||||
import static org.springframework.http.MediaType.MULTIPART_FORM_DATA_VALUE;
|
||||
|
||||
/**
|
||||
* @author wangsiqian
|
||||
* @since 2024/02/27
|
||||
*/
|
||||
@FeignClient(
|
||||
name = "oss",
|
||||
url = "http://oss:9123"
|
||||
)
|
||||
public interface WebFileServiceApi {
|
||||
/**
|
||||
* OBS:文件上传(断点续传)
|
||||
*
|
||||
* @param appCode 应用编码
|
||||
* @param bizScene 业务场景
|
||||
* @param file MultipartFile
|
||||
* @return WebFileUploadVo
|
||||
*/
|
||||
@PostMapping(value = "/webApi/v1/file2", consumes = MULTIPART_FORM_DATA_VALUE)
|
||||
CommonResponse<WebFileUploadVo> uploadObs(@Valid @RequestParam("appCode") String appCode,
|
||||
@Valid @RequestParam("bizScene") String bizScene,
|
||||
@Valid @RequestPart MultipartFile file);
|
||||
}
|
||||
@ -0,0 +1,30 @@
|
||||
package cn.axzo.oss.http.model;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
/**
|
||||
* @author hucf
|
||||
* @since 2024/3/6 15:11
|
||||
**/
|
||||
@Data
|
||||
public class DownloadFileFromObsRequest {
|
||||
/**
|
||||
* 文件uuid
|
||||
*/
|
||||
@NotBlank(message = "文件uuid不能为空")
|
||||
private String fileKey;
|
||||
|
||||
/**
|
||||
* 图片样式
|
||||
*/
|
||||
private String style;
|
||||
|
||||
/**
|
||||
* 下载方式:1:流式下载;2:断点续传方式下载
|
||||
*/
|
||||
@NotNull(message = "下载方式不能为空")
|
||||
private Integer fileDownloadType;
|
||||
}
|
||||
@ -0,0 +1,46 @@
|
||||
package cn.axzo.oss.http.model;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.InputStream;
|
||||
|
||||
/**
|
||||
* @author hucf
|
||||
* @since 2024/3/6 15:15
|
||||
**/
|
||||
@Data
|
||||
public class DownloadFileFromObsResponse {
|
||||
/**
|
||||
* 文件 URL
|
||||
*/
|
||||
private String url;
|
||||
/**
|
||||
* 文件 Key
|
||||
*/
|
||||
private String fileKey;
|
||||
|
||||
/**
|
||||
* URL MD5
|
||||
*/
|
||||
private String urlMd5;
|
||||
|
||||
/**
|
||||
* 文件名称
|
||||
*/
|
||||
private String fileName;
|
||||
|
||||
/**
|
||||
* 文件大小
|
||||
*/
|
||||
private Long fileSize;
|
||||
|
||||
/**
|
||||
* 文件格式
|
||||
*/
|
||||
private String fileFormat;
|
||||
|
||||
/**
|
||||
* 文件流
|
||||
*/
|
||||
private InputStream fileStream;
|
||||
}
|
||||
@ -0,0 +1,44 @@
|
||||
package cn.axzo.oss.http.model;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @author hucf
|
||||
* @since 2024/3/11 18:21
|
||||
**/
|
||||
@Data
|
||||
public class TemporaryUrlAccessRes {
|
||||
/**
|
||||
* 文件 URL
|
||||
*/
|
||||
private String url;
|
||||
/**
|
||||
* 文件 Key
|
||||
*/
|
||||
private String fileKey;
|
||||
|
||||
/**
|
||||
* URL MD5
|
||||
*/
|
||||
private String urlMd5;
|
||||
|
||||
/**
|
||||
* 文件名称
|
||||
*/
|
||||
private String fileName;
|
||||
|
||||
/**
|
||||
* 文件大小
|
||||
*/
|
||||
private Long fileSize;
|
||||
|
||||
/**
|
||||
* 文件格式
|
||||
*/
|
||||
private String fileFormat;
|
||||
|
||||
/**
|
||||
* obs:临时url
|
||||
*/
|
||||
private String signedUrl;
|
||||
}
|
||||
@ -1,4 +1,4 @@
|
||||
package cn.axzo.oss.client.vo;
|
||||
package cn.axzo.oss.http.model;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@ -25,6 +25,10 @@
|
||||
<groupId>com.aliyun.oss</groupId>
|
||||
<artifactId>aliyun-sdk-oss</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.huaweicloud</groupId>
|
||||
<artifactId>esdk-obs-java-bundle</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
|
||||
@ -0,0 +1,23 @@
|
||||
package cn.axzo.oss.integration.s3;
|
||||
|
||||
import com.obs.services.model.TemporarySignatureResponse;
|
||||
|
||||
import java.io.InputStream;
|
||||
|
||||
/**
|
||||
* 华为云obs
|
||||
*
|
||||
* @author hucf
|
||||
* @since 2024/1/15 11:37
|
||||
**/
|
||||
public interface HuaWeiCloudService {
|
||||
String uploadFile(String bucketName, String fileName, String appCode, InputStream srcStream);
|
||||
|
||||
String checkPointUploadFile(String bucketName, String fileName, String appCode, InputStream srcStream, String filePath);
|
||||
|
||||
String multipartUpload(String bucketName, String fileName, String appCode, InputStream srcStream);
|
||||
|
||||
InputStream getObject(String bucketName, String objectKey, Integer fileDownloadType);
|
||||
|
||||
TemporarySignatureResponse createTemporarySignature(String bucketName, String objectKey);
|
||||
}
|
||||
@ -0,0 +1,62 @@
|
||||
package cn.axzo.oss.integration.s3.client;
|
||||
|
||||
import cn.axzo.oss.common.enums.CodeEnum;
|
||||
import cn.axzo.oss.common.exception.S3Exception;
|
||||
import cn.axzo.oss.common.utils.Utility;
|
||||
import cn.axzo.oss.integration.s3.base.OssClientBase;
|
||||
import cn.axzo.oss.integration.s3.config.HuaWeiCloudObsConfig;
|
||||
import cn.azxo.framework.common.utils.LogUtil;
|
||||
import com.obs.services.ObsClient;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
|
||||
/**
|
||||
* 华为云obs客户端
|
||||
*
|
||||
* @author hucf
|
||||
* @since 2024/1/15 09:59
|
||||
**/
|
||||
@Component
|
||||
@Slf4j
|
||||
public class HuaWeiCloudObsClient implements OssClientBase {
|
||||
|
||||
private volatile ObsClient instance = null;
|
||||
|
||||
@Autowired
|
||||
private HuaWeiCloudObsConfig huaWeiCloudObsConfig;
|
||||
|
||||
@Override
|
||||
public ObsClient getClient() {
|
||||
if (Utility.objIsNull(instance)){
|
||||
throw new S3Exception(CodeEnum.OBS_CLIENT_NULL.getCode(),"oss客户端未初始化");
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
@Override
|
||||
public void initClient() {
|
||||
log.info("accessKeyId = {},secretAccessKey = {}, initClient endpoint = {}",
|
||||
huaWeiCloudObsConfig.getAccessKeyId(),
|
||||
huaWeiCloudObsConfig.getSecretAccessKey(),
|
||||
huaWeiCloudObsConfig.getEndPoint());
|
||||
try {
|
||||
instance = new ObsClient(
|
||||
huaWeiCloudObsConfig.getAccessKeyId(),
|
||||
huaWeiCloudObsConfig.getSecretAccessKey(),
|
||||
huaWeiCloudObsConfig.getEndPoint()
|
||||
);
|
||||
} catch (Exception exception) {
|
||||
instance = null;
|
||||
LogUtil.error("initClient error = {}", exception);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEndpoint() {
|
||||
return huaWeiCloudObsConfig.getEndPoint();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,65 @@
|
||||
package cn.axzo.oss.integration.s3.config;
|
||||
|
||||
import lombok.Data;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.cloud.context.config.annotation.RefreshScope;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* 华为云对象存储服务OBS配置
|
||||
*
|
||||
* @author hucf
|
||||
* @since 2024/1/12 15:11
|
||||
**/
|
||||
@Configuration
|
||||
@RefreshScope
|
||||
@Data
|
||||
public class HuaWeiCloudObsConfig {
|
||||
/**
|
||||
* AK
|
||||
*/
|
||||
@Value("${huaweicloud.obs.accessKeyId}")
|
||||
private String accessKeyId;
|
||||
|
||||
/**
|
||||
* SK
|
||||
*/
|
||||
@Value("${huaweicloud.obs.secretAccessKey}")
|
||||
private String secretAccessKey;
|
||||
|
||||
/**
|
||||
* 终端节点
|
||||
*/
|
||||
@Value("${huaweicloud.obs.endpoint}")
|
||||
private String endPoint;
|
||||
|
||||
/**
|
||||
* 分段上传时的最大并发数
|
||||
*/
|
||||
@Value("${huaweicloud.checkpoint.task-num}")
|
||||
private String taskNum;
|
||||
|
||||
/**
|
||||
* 分段大小
|
||||
*/
|
||||
@Value("${huaweicloud.checkpoint.part-size}")
|
||||
private String partSize;
|
||||
|
||||
/**
|
||||
* 是否开启断点续传模式
|
||||
*/
|
||||
@Value("${huaweicloud.checkpoint.enable-check-point}")
|
||||
private String enableCheckPoint;
|
||||
|
||||
/**
|
||||
* 是否开启请求头域自动编码
|
||||
*/
|
||||
@Value("${huaweicloud.checkpoint.encode-headers}")
|
||||
private String encodeHeaders;
|
||||
|
||||
/**
|
||||
* 是否开启请求头域自动编码
|
||||
*/
|
||||
@Value("${huaweicloud.profiles.active}")
|
||||
private String profilesActive;
|
||||
}
|
||||
@ -0,0 +1,323 @@
|
||||
package cn.axzo.oss.integration.s3.impl;
|
||||
|
||||
import cn.axzo.oss.common.enums.FileDownloadTypeEnum;
|
||||
import cn.axzo.oss.integration.s3.HuaWeiCloudService;
|
||||
import cn.axzo.oss.integration.s3.client.HuaWeiCloudObsClient;
|
||||
import cn.axzo.oss.integration.s3.config.HuaWeiCloudObsConfig;
|
||||
import cn.azxo.framework.common.utils.LogUtil;
|
||||
import cn.hutool.core.io.FileUtil;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.obs.services.ObsClient;
|
||||
import com.obs.services.exception.ObsException;
|
||||
import com.obs.services.model.*;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 华为云OBS
|
||||
*
|
||||
* @author hucf
|
||||
* @since 2024/1/15 11:41
|
||||
**/
|
||||
@Service
|
||||
@Slf4j
|
||||
public class HuaWeiCloudServiceImpl implements HuaWeiCloudService {
|
||||
private static final String APPCODE_CMS = "cms";
|
||||
|
||||
@Autowired
|
||||
private HuaWeiCloudObsClient huaWeiCloudObsClient;
|
||||
|
||||
@Autowired
|
||||
private HuaWeiCloudObsConfig huaWeiCloudObsConfig;
|
||||
|
||||
/**
|
||||
* 上传文件到OBS:普通方式
|
||||
*
|
||||
* @param bucketName 桶名称
|
||||
* @param fileName 文件名
|
||||
* @param appCode 应用编码
|
||||
* @param srcStream 文件流
|
||||
* @return fileUrl
|
||||
*/
|
||||
@Override
|
||||
public String uploadFile(String bucketName, String fileName, String appCode, InputStream srcStream) {
|
||||
ObsClient obsClient = huaWeiCloudObsClient.getClient();
|
||||
|
||||
// 创建文件夹
|
||||
String objectKey = huaWeiCloudObsConfig.getProfilesActive() + "/" + appCode + "/" + fileName;
|
||||
try {
|
||||
if (APPCODE_CMS.equals(appCode)) {
|
||||
// 普通上传方式
|
||||
PutObjectRequest request = new PutObjectRequest();
|
||||
request.setBucketName(bucketName);
|
||||
request.setObjectKey(objectKey);
|
||||
request.setInput(srcStream);
|
||||
request.setIsEncodeHeaders(true);
|
||||
PutObjectResult putObjectResult = obsClient.putObject(bucketName, objectKey, srcStream);
|
||||
return putObjectResult.getObjectUrl();
|
||||
} else {
|
||||
// 创建上传文件的元信息,通过文件云信息设置HTTP Header
|
||||
ObjectMetadata metadata = new ObjectMetadata();
|
||||
// 设置内容被下载时的名称
|
||||
metadata.setContentDisposition("attachment;filename=\"" + URLEncoder.encode(fileName, "utf-8") + "\"");
|
||||
metadata.setContentEncoding("utf-8");
|
||||
PutObjectResult putObjectResult = obsClient.putObject(bucketName, objectKey, srcStream, metadata);
|
||||
return putObjectResult.getObjectUrl();
|
||||
}
|
||||
} catch (ObsException exception) {
|
||||
LogUtil.error("uploadByStream ObsException", exception);
|
||||
return "";
|
||||
} catch (Exception e) {
|
||||
LogUtil.error("uploadByStream ClientException", e);
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 上传文件到OBS:断点续传
|
||||
*
|
||||
* @param bucketName 桶名称
|
||||
* @param fileName 文件名
|
||||
* @param appCode 应用编码
|
||||
* @param srcStream 文件流
|
||||
* @return fileUrl
|
||||
*/
|
||||
@Override
|
||||
public String checkPointUploadFile(String bucketName, String fileName, String appCode, InputStream srcStream, String filePath) {
|
||||
ObsClient obsClient = huaWeiCloudObsClient.getClient();
|
||||
|
||||
// 创建文件夹
|
||||
String objectKey = huaWeiCloudObsConfig.getProfilesActive() + "/" + appCode + "/" + fileName;
|
||||
try {
|
||||
if (APPCODE_CMS.equals(appCode)) {
|
||||
// 断点续传
|
||||
CompleteMultipartUploadResult completeMultipartUploadResult =
|
||||
this.uploadFile(obsClient, bucketName, objectKey, fileName, null, filePath);
|
||||
int statusCode = completeMultipartUploadResult.getStatusCode();
|
||||
log.info("上传文件返回的状态码,{}", statusCode);
|
||||
log.info("上传文件返回的url,{}", completeMultipartUploadResult.getObjectUrl());
|
||||
boolean delFlag = FileUtil.del(filePath);
|
||||
log.info("断点续传成功,删除临时文件:{}", delFlag);
|
||||
return completeMultipartUploadResult.getObjectUrl();
|
||||
} else {
|
||||
// 创建上传文件的元信息,通过文件云信息设置HTTP Header
|
||||
ObjectMetadata metadata = new ObjectMetadata();
|
||||
// 设置内容被下载时的名称
|
||||
metadata.setContentDisposition("attachment;filename=\"" + URLEncoder.encode(fileName, "utf-8") + "\"");
|
||||
metadata.setContentEncoding("utf-8");
|
||||
CompleteMultipartUploadResult completeMultipartUploadResult =
|
||||
this.uploadFile(obsClient, bucketName, objectKey, fileName, metadata, filePath);
|
||||
boolean delFlag = FileUtil.del(filePath);
|
||||
log.info("断点续传成功,删除临时文件:{}", delFlag);
|
||||
return completeMultipartUploadResult.getObjectUrl();
|
||||
}
|
||||
} catch (ObsException exception) {
|
||||
LogUtil.error("uploadByStream ObsException", exception);
|
||||
return "";
|
||||
} catch (Exception e) {
|
||||
LogUtil.error("uploadByStream ClientException", e);
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 上传文件到OBS:分段上传
|
||||
*
|
||||
* @param bucketName 桶名称
|
||||
* @param fileName 文件名
|
||||
* @param appCode 应用编码
|
||||
* @param srcStream 文件流
|
||||
* @return fileUrl
|
||||
*/
|
||||
@Override
|
||||
public String multipartUpload(String bucketName, String fileName, String appCode, InputStream srcStream) {
|
||||
|
||||
ObsClient obsClient = huaWeiCloudObsClient.getClient();
|
||||
// 创建文件夹
|
||||
String objectKey = huaWeiCloudObsConfig.getProfilesActive() + "/" + appCode + "/" + fileName;
|
||||
|
||||
try {
|
||||
// 初始化分段上传任务
|
||||
InitiateMultipartUploadResult initiateMultipartUploadResult =
|
||||
this.initiateMultipartUploadResult(obsClient, bucketName, objectKey);
|
||||
String uploadId = initiateMultipartUploadResult.getUploadId();
|
||||
|
||||
// 上传段
|
||||
UploadPartResult uploadPartResult = this.uploadPart(obsClient, bucketName, objectKey, uploadId, srcStream);
|
||||
|
||||
// 合并段
|
||||
CompleteMultipartUploadResult completeMultipartUploadResult =
|
||||
this.completeMultipartUpload(uploadPartResult, obsClient, bucketName, objectKey, uploadId);
|
||||
|
||||
return completeMultipartUploadResult.getLocation();
|
||||
} catch (ObsException exception) {
|
||||
LogUtil.error("uploadByStream ObsException", exception);
|
||||
return "";
|
||||
} catch (Exception e) {
|
||||
LogUtil.error("uploadByStream ClientException", e);
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
// 初始化分段上传任务
|
||||
private InitiateMultipartUploadResult initiateMultipartUploadResult(ObsClient obsClient, String bucketName,
|
||||
String objectKey) {
|
||||
InitiateMultipartUploadRequest request = new InitiateMultipartUploadRequest();
|
||||
request.setBucketName(bucketName);
|
||||
request.setObjectKey(objectKey);
|
||||
return obsClient.initiateMultipartUpload(request);
|
||||
}
|
||||
|
||||
// 上传段
|
||||
private UploadPartResult uploadPart(ObsClient obsClient, String bucketName, String objectKey, String uploadId,
|
||||
InputStream srcStream) {
|
||||
|
||||
UploadPartRequest uploadPartRequest = new UploadPartRequest();
|
||||
uploadPartRequest.setBucketName(bucketName);
|
||||
uploadPartRequest.setObjectKey(objectKey);
|
||||
// todo:计算段号
|
||||
uploadPartRequest.setPartNumber(120);
|
||||
uploadPartRequest.setUploadId(uploadId);
|
||||
uploadPartRequest.setInput(srcStream);
|
||||
return obsClient.uploadPart(uploadPartRequest);
|
||||
}
|
||||
|
||||
// 合并段
|
||||
private CompleteMultipartUploadResult completeMultipartUpload(UploadPartResult uploadPartResult,
|
||||
ObsClient obsClient,
|
||||
String bucketName,
|
||||
String objectKey,
|
||||
String uploadId) {
|
||||
// 构建待合并的段列表
|
||||
List<PartEtag> partEtagList = new ArrayList<>();
|
||||
PartEtag partEtag = new PartEtag();
|
||||
partEtag.setEtag(uploadPartResult.getEtag());
|
||||
partEtag.setPartNumber(uploadPartResult.getPartNumber());
|
||||
partEtagList.add(partEtag);
|
||||
|
||||
CompleteMultipartUploadRequest completeMultipartUploadRequest = new CompleteMultipartUploadRequest();
|
||||
completeMultipartUploadRequest.setBucketName(bucketName);
|
||||
completeMultipartUploadRequest.setObjectKey(objectKey);
|
||||
completeMultipartUploadRequest.setPartEtag(partEtagList);
|
||||
completeMultipartUploadRequest.setUploadId(uploadId);
|
||||
return obsClient.completeMultipartUpload(completeMultipartUploadRequest);
|
||||
}
|
||||
|
||||
// 断点续传
|
||||
private CompleteMultipartUploadResult uploadFile(ObsClient obsClient, String bucketName, String objectKey,
|
||||
String fileName, ObjectMetadata metadata, String filePath) {
|
||||
UploadFileRequest request = new UploadFileRequest(bucketName, objectKey, fileName);
|
||||
// 设置待上传的本地文件,fileName为待上传的本地文件路径,需要指定到具体带文件后缀的文件名
|
||||
request.setUploadFile(filePath);
|
||||
// 设置分段上传时的最大并发数
|
||||
request.setTaskNum(Integer.parseInt(huaWeiCloudObsConfig.getTaskNum()));
|
||||
// 设置分段大小为10MB
|
||||
request.setPartSize(Long.parseLong(huaWeiCloudObsConfig.getPartSize()));
|
||||
// 开启断点续传模式
|
||||
request.setEnableCheckpoint(Boolean.parseBoolean(huaWeiCloudObsConfig.getEnableCheckPoint()));
|
||||
// 开启请求头域自动编码
|
||||
request.setIsEncodeHeaders(Boolean.parseBoolean(huaWeiCloudObsConfig.getEncodeHeaders()));
|
||||
// 对象元数据
|
||||
request.setObjectMetadata(metadata);
|
||||
return obsClient.uploadFile(request);
|
||||
}
|
||||
|
||||
/**
|
||||
* obs下载文件:流式下载
|
||||
*
|
||||
* @param bucketName 桶名称
|
||||
* @param objectKey 对象名称
|
||||
* @return InputStream
|
||||
*/
|
||||
@Override
|
||||
public InputStream getObject(String bucketName, String objectKey, Integer fileDownloadType) {
|
||||
ObsClient obsClient = huaWeiCloudObsClient.getClient();
|
||||
if (FileDownloadTypeEnum.STREAM_DOWNLOAD.getCode().equals(fileDownloadType)) {
|
||||
try {
|
||||
GetObjectRequest request = new GetObjectRequest();
|
||||
request.setBucketName(bucketName);
|
||||
request.setObjectKey(objectKey);
|
||||
|
||||
ObsObject object = obsClient.getObject(request);
|
||||
log.info("下载华为云OBS文件成功");
|
||||
return object.getObjectContent();
|
||||
} catch (ObsException obsException) {
|
||||
log.warn("下载华为云OBS文件失败,HTTP Code:{}, Error Code:{}, Request ID:{}, Host ID:{}, Error Message:{}",
|
||||
obsException.getResponseCode(),
|
||||
obsException.getErrorCode(),
|
||||
obsException.getErrorRequestId(),
|
||||
obsException.getErrorHostId(),
|
||||
obsException.getErrorMessage());
|
||||
}
|
||||
} else if (FileDownloadTypeEnum.CHECK_POINT_DOWNLOAD.getCode().equals(fileDownloadType)) {
|
||||
try {
|
||||
DownloadFileRequest request = new DownloadFileRequest(bucketName, objectKey);
|
||||
// 设置下载对象的本地文件全路径,当该值为空时,默认为当前程序的运行目录。
|
||||
request.setDownloadFile("");
|
||||
// 设置分段下载时的最大并发数
|
||||
request.setTaskNum(Integer.parseInt(huaWeiCloudObsConfig.getTaskNum()));
|
||||
// 设置分段大小为10MB
|
||||
request.setPartSize(Long.parseLong(huaWeiCloudObsConfig.getPartSize()));
|
||||
// 是否开启断点续传模式
|
||||
request.setEnableCheckpoint(Boolean.parseBoolean(huaWeiCloudObsConfig.getEnableCheckPoint()));
|
||||
// 是否自动解码响应头
|
||||
request.setIsEncodeHeaders(Boolean.parseBoolean(huaWeiCloudObsConfig.getEncodeHeaders()));
|
||||
|
||||
DownloadFileResult downloadFileResult = obsClient.downloadFile(request);
|
||||
String etag = downloadFileResult.getObjectMetadata().getEtag();
|
||||
log.info("下载华为云OBS文件成功");
|
||||
} catch (NumberFormatException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (ObsException obsException) {
|
||||
log.warn("下载华为云OBS文件失败,HTTP Code:{}, Error Code:{}, Request ID:{}, Host ID:{}, Error Message:{}",
|
||||
obsException.getResponseCode(),
|
||||
obsException.getErrorCode(),
|
||||
obsException.getErrorRequestId(),
|
||||
obsException.getErrorHostId(),
|
||||
obsException.getErrorMessage());
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取OBS临时url
|
||||
*
|
||||
* @param bucketName 桶名称
|
||||
* @param objectKey 对象名称
|
||||
* @return TemporarySignatureResponse
|
||||
*/
|
||||
@Override
|
||||
public TemporarySignatureResponse createTemporarySignature(String bucketName, String objectKey) {
|
||||
TemporarySignatureRequest request = new TemporarySignatureRequest();
|
||||
// 桶名称
|
||||
request.setBucketName(bucketName);
|
||||
// 对象名称
|
||||
request.setObjectKey(objectKey);
|
||||
// HTTP方法类型
|
||||
request.setMethod(HttpMethodEnum.GET);
|
||||
// 带授权信息的URL的过期时间300秒
|
||||
request.setExpires(300L);
|
||||
// 发起请求的时间
|
||||
request.setRequestDate(new Date());
|
||||
|
||||
try {
|
||||
ObsClient obsClient = huaWeiCloudObsClient.getClient();
|
||||
TemporarySignatureResponse response = obsClient.createTemporarySignature(request);
|
||||
log.info("response = {}", JSONUtil.toJsonStr(response));
|
||||
return response;
|
||||
} catch (Exception exception) {
|
||||
log.warn("获取临时url发生异常, exception = {}", exception.getMessage());
|
||||
log.warn("异常信息:");
|
||||
exception.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -16,5 +16,5 @@ public interface AppChannelBucketManager {
|
||||
* @param appCode appcode
|
||||
* @return
|
||||
*/
|
||||
AppChannelBucket getByAppCode(String appCode);
|
||||
AppChannelBucket getByAppCode(String appCode, Integer fileUploadType);
|
||||
}
|
||||
|
||||
@ -33,7 +33,8 @@ public interface FileManager {
|
||||
* @param fileContent
|
||||
* @return
|
||||
*/
|
||||
String uploadByStream(String bulkName, String keyPath, String fileName, String appCode, byte[] fileContent);
|
||||
String uploadByStream(String bulkName, String keyPath, String fileName, String appCode, byte[] fileContent,
|
||||
Integer channelType, Integer fileUploadType, String filePath);
|
||||
|
||||
/**
|
||||
* 下载文件
|
||||
@ -50,4 +51,8 @@ public interface FileManager {
|
||||
String multipartUploadComplete(String bucketName, String tgtFileKey, String uploadId, List<PartETag> partETags);
|
||||
|
||||
String multipartUploadFile(String bucketName, String tgtFileKey, MultipartFile file);
|
||||
|
||||
InputStream downloadObsFile(String bucketName, String objectKey, Integer fileDownloadType);
|
||||
|
||||
String getTempUrlFromOns(String bucketName, String objectKey);
|
||||
}
|
||||
|
||||
@ -20,6 +20,7 @@ public class ServerFileUploadDto {
|
||||
private String bizScene;
|
||||
private String fileName;
|
||||
private byte[] fileContent;
|
||||
private String filePath;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
|
||||
@ -45,4 +45,9 @@ public class ServerFileDownloadResponse {
|
||||
* 文件流
|
||||
*/
|
||||
private InputStream fileStream;
|
||||
|
||||
/**
|
||||
* obs:临时url
|
||||
*/
|
||||
private String signedUrl;
|
||||
}
|
||||
|
||||
@ -34,8 +34,8 @@ public class AppChannelBucketManagerImpl implements AppChannelBucketManager {
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public AppChannelBucket getByAppCode(String appCode) {
|
||||
List<AppChannelBucket> appChannelBuckets = appChannelBucketDao.getByAppCode(appCode);
|
||||
public AppChannelBucket getByAppCode(String appCode, Integer channelType) {
|
||||
List<AppChannelBucket> appChannelBuckets = appChannelBucketDao.getByAppCode(appCode, channelType);
|
||||
BizException.isEmpty(appChannelBuckets, CodeEnum.APP_CHANNEL_BUCKET_NOT_FOUND);
|
||||
|
||||
// 找到最优渠道
|
||||
|
||||
@ -1,11 +1,15 @@
|
||||
package cn.axzo.oss.manager.impl;
|
||||
|
||||
import cn.axzo.oss.common.enums.ChannelTypeEnum;
|
||||
import cn.axzo.oss.common.enums.FileUploadTypeEnum;
|
||||
import cn.axzo.oss.common.enums.StorageUnitEnum;
|
||||
import cn.axzo.oss.common.utils.BeanConvertUtil;
|
||||
import cn.axzo.oss.integration.s3.AliOssService;
|
||||
import cn.axzo.oss.integration.s3.HuaWeiCloudService;
|
||||
import cn.axzo.oss.manager.api.FileManager;
|
||||
import cn.axzo.oss.manager.api.dto.PartETag;
|
||||
import cn.axzo.oss.manager.api.dto.request.MultipartUploadDto;
|
||||
import cn.axzo.oss.manager.api.dto.request.MultipartUploadFileDto;
|
||||
import com.obs.services.model.TemporarySignatureResponse;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@ -30,6 +34,9 @@ public class FileManagerImpl implements FileManager {
|
||||
@Autowired
|
||||
private AliOssService aliOssService;
|
||||
|
||||
@Autowired
|
||||
private HuaWeiCloudService huaWeiCloudService;
|
||||
|
||||
/**
|
||||
* 删除文件
|
||||
*
|
||||
@ -46,11 +53,35 @@ public class FileManagerImpl implements FileManager {
|
||||
* @param bulkName 默认的取值为
|
||||
* @param keyPath key的前置路径
|
||||
*/
|
||||
public String uploadByStream(String bulkName, String keyPath, String fileName, String appCode, byte[] fileContent) {
|
||||
public String uploadByStream(String bulkName, String keyPath, String fileName, String appCode, byte[] fileContent,
|
||||
Integer channelType, Integer fileUploadType, String filePath) {
|
||||
|
||||
InputStream inputStream = new ByteArrayInputStream(fileContent);
|
||||
|
||||
return aliOssService.uploadByStream(bulkName, keyPath, fileName, appCode, inputStream);
|
||||
if (channelType.equals(ChannelTypeEnum.OBS.getCode())) {
|
||||
// 断点续传长度限制:断点续传上传接口传入的文件大小至少要100K以上
|
||||
if (fileUploadType.equals(FileUploadTypeEnum.CHECK_POINT.getCode())) {
|
||||
int checkPointLengthLimit = StorageUnitEnum.KB.getSize() * 100;
|
||||
int fileLength = fileContent.length;
|
||||
if (fileLength < checkPointLengthLimit) {
|
||||
fileUploadType = FileUploadTypeEnum.DEFAULT_UPLOAD.getCode();
|
||||
}
|
||||
}
|
||||
|
||||
// 上传文件到OBS
|
||||
if (fileUploadType.equals(FileUploadTypeEnum.DEFAULT_UPLOAD.getCode())) {
|
||||
return huaWeiCloudService.uploadFile(bulkName, fileName, appCode, inputStream);
|
||||
} else if (fileUploadType.equals(FileUploadTypeEnum.CHECK_POINT.getCode())) {
|
||||
return huaWeiCloudService.checkPointUploadFile(bulkName, fileName, appCode, inputStream, filePath);
|
||||
} else {
|
||||
return huaWeiCloudService.multipartUpload(bulkName, fileName, appCode, inputStream);
|
||||
}
|
||||
}
|
||||
|
||||
// 上传文件到阿里云
|
||||
else {
|
||||
return aliOssService.uploadByStream(bulkName, keyPath, fileName, appCode, inputStream);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -94,4 +125,13 @@ public class FileManagerImpl implements FileManager {
|
||||
}
|
||||
return partETagList;
|
||||
}
|
||||
|
||||
public InputStream downloadObsFile(String bucketName, String objectKey, Integer fileDownloadType) {
|
||||
return huaWeiCloudService.getObject(bucketName, objectKey, fileDownloadType);
|
||||
}
|
||||
|
||||
public String getTempUrlFromOns(String bucketName, String objectKey) {
|
||||
TemporarySignatureResponse response = huaWeiCloudService.createTemporarySignature(bucketName, objectKey);
|
||||
return response.getSignedUrl();
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,6 +3,7 @@ package cn.axzo.oss.service.api;
|
||||
import cn.axzo.framework.auth.domain.ContextInfo;
|
||||
import cn.axzo.oss.manager.api.dto.request.*;
|
||||
import cn.axzo.oss.manager.api.dto.response.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
@ -38,11 +39,18 @@ public interface FileService {
|
||||
|
||||
ServerFileDownloadResponse download(ServerFileDownloadDto dto);
|
||||
|
||||
MultipartUploadInitResponse multipartUploadInit(MultipartUploadInitDto multipartUploadInitDto);
|
||||
MultipartUploadInitResponse multipartUploadInit(MultipartUploadInitDto multipartUploadInitDto, Integer channelType);
|
||||
|
||||
MultipartUploadResponse multipartUpload(MultipartUploadDto dto);
|
||||
MultipartUploadResponse multipartUpload(MultipartUploadDto dto, Integer channelType);
|
||||
|
||||
FileInformationResponse multipartUploadComplete(MultipartUploadCompleteDto dto);
|
||||
FileInformationResponse multipartUploadComplete(MultipartUploadCompleteDto dto, Integer channelType);
|
||||
|
||||
FileInformationResponse multipartUploadFile(MultipartUploadFileDto dto);
|
||||
FileInformationResponse multipartUploadFile(MultipartUploadFileDto dto, Integer channelType);
|
||||
|
||||
ServerFileUploadResponse uploadObs(ServerFileUploadDto dto, ContextInfo.LiteSaasContext liteSaasContext,
|
||||
Integer fileUploadType);
|
||||
|
||||
String getFilePath(MultipartFile file);
|
||||
|
||||
ServerFileDownloadResponse getObject(ServerFileDownloadDto dto, Integer fileDownloadType);
|
||||
}
|
||||
|
||||
@ -22,6 +22,10 @@
|
||||
<groupId>cn.axzo.oss</groupId>
|
||||
<artifactId>oss-manager</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.huaweicloud</groupId>
|
||||
<artifactId>esdk-obs-java-bundle</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
|
||||
@ -6,15 +6,14 @@ import cn.axzo.log.platform.client.model.OperateLogReq;
|
||||
import cn.axzo.oss.common.constans.CommonConstants;
|
||||
import cn.axzo.oss.common.constans.CommonConstants.FileStatus;
|
||||
import cn.axzo.oss.common.constans.CommonConstants.TableDelete;
|
||||
import cn.axzo.oss.common.enums.CodeEnum;
|
||||
import cn.axzo.oss.common.enums.FileClassEnum;
|
||||
import cn.axzo.oss.common.enums.FileStatusEnum;
|
||||
import cn.axzo.oss.common.enums.*;
|
||||
import cn.axzo.oss.common.exception.BizException;
|
||||
import cn.axzo.oss.common.utils.JsonUtil;
|
||||
import cn.axzo.oss.common.utils.Utility;
|
||||
import cn.axzo.oss.dal.entity.*;
|
||||
import cn.axzo.oss.dal.repository.FileAppDao;
|
||||
import cn.axzo.oss.dal.repository.FileDao;
|
||||
import cn.axzo.oss.integration.s3.config.HuaWeiCloudObsConfig;
|
||||
import cn.axzo.oss.manager.api.AppChannelBucketManager;
|
||||
import cn.axzo.oss.manager.api.FileBusinessSceneManager;
|
||||
import cn.axzo.oss.manager.api.FileManager;
|
||||
@ -30,9 +29,14 @@ import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.stream.Collectors;
|
||||
@ -50,12 +54,16 @@ import static cn.axzo.oss.common.constans.CommonConstants.APP_PRO_BUCKET_NAME;
|
||||
public class FileServiceImpl implements FileService {
|
||||
|
||||
private static final String FILE_UPLOAD_CODE = "OSS_FILE_UPLOAD";
|
||||
|
||||
private static final String OBS_FILE_UPLOAD_CODE = "OBS_FILE_UPLOAD";
|
||||
private static final String FILE_UPLOAD_NAME = "文件上传";
|
||||
|
||||
private static final String IS_URL = "https://";
|
||||
|
||||
private static final String HTTP_COM = ".com/";
|
||||
|
||||
private static final String SEPARATOR = java.io.File.separator;
|
||||
|
||||
@Autowired
|
||||
private FileManager fileManager;
|
||||
|
||||
@ -77,6 +85,9 @@ public class FileServiceImpl implements FileService {
|
||||
@Autowired
|
||||
private LogPlatClient logPlatClient;
|
||||
|
||||
@Autowired
|
||||
private HuaWeiCloudObsConfig huaWeiCloudObsConfig;
|
||||
|
||||
/**
|
||||
* 删除文件
|
||||
*
|
||||
@ -136,7 +147,8 @@ public class FileServiceImpl implements FileService {
|
||||
*/
|
||||
@Override
|
||||
public ServerFileUploadResponse upload(ServerFileUploadDto dto, ContextInfo.LiteSaasContext liteSaasContext) {
|
||||
File ossFile = uploadFileAndGetFile(dto);
|
||||
File ossFile = uploadFileAndGetFile(dto, ChannelTypeEnum.OSS.getCode(),
|
||||
FileUploadTypeEnum.DEFAULT_UPLOAD.getCode());
|
||||
//操作日志记录
|
||||
operateLog(dto.toString(), "", FILE_UPLOAD_CODE, FILE_UPLOAD_NAME, liteSaasContext);
|
||||
return setResponse(ossFile);
|
||||
@ -144,15 +156,16 @@ public class FileServiceImpl implements FileService {
|
||||
|
||||
@Override
|
||||
public FileInformationResponse uploadV2(String serviceName, ServerFileUploadDto request, ContextInfo.LiteSaasContext liteSaasContext) {
|
||||
File ossFile = uploadFileAndGetFile(request);
|
||||
File ossFile = uploadFileAndGetFile(request, ChannelTypeEnum.OSS.getCode(),
|
||||
FileUploadTypeEnum.DEFAULT_UPLOAD.getCode());
|
||||
//操作日志记录
|
||||
operateLog(request.toString(), serviceName, FILE_UPLOAD_CODE, FILE_UPLOAD_NAME, liteSaasContext);
|
||||
return setFileInfoResp(ossFile);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MultipartUploadInitResponse multipartUploadInit(MultipartUploadInitDto dto) {
|
||||
FileUploadConfig fileUploadConfig = getFileUploadConfig(dto.getAppCode(), dto.getBizScene());
|
||||
public MultipartUploadInitResponse multipartUploadInit(MultipartUploadInitDto dto, Integer channelType) {
|
||||
FileUploadConfig fileUploadConfig = getFileUploadConfig(dto.getAppCode(), dto.getBizScene(), channelType);
|
||||
// 判断容量
|
||||
String fileConform = isFileConform(fileUploadConfig, 10, dto.getFileName());
|
||||
String uuid = Utility.getUUID();
|
||||
@ -167,8 +180,8 @@ public class FileServiceImpl implements FileService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public MultipartUploadResponse multipartUpload(MultipartUploadDto dto) {
|
||||
FileUploadConfig fileUploadConfig = getFileUploadConfig(dto.getAppCode(), dto.getBizScene());
|
||||
public MultipartUploadResponse multipartUpload(MultipartUploadDto dto, Integer channelType) {
|
||||
FileUploadConfig fileUploadConfig = getFileUploadConfig(dto.getAppCode(), dto.getBizScene(), channelType);
|
||||
// 判断容量
|
||||
isFileConform(fileUploadConfig, dto.getFileContent().length, dto.getFileName());
|
||||
|
||||
@ -182,13 +195,13 @@ public class FileServiceImpl implements FileService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileInformationResponse multipartUploadFile(MultipartUploadFileDto dto) {
|
||||
File ossFile = multipartUploadAndGetFile(dto);
|
||||
public FileInformationResponse multipartUploadFile(MultipartUploadFileDto dto, Integer fileUploadType) {
|
||||
File ossFile = multipartUploadAndGetFile(dto, fileUploadType);
|
||||
return setFileInfoResp(dto.getFile().getSize(), ossFile);
|
||||
}
|
||||
|
||||
private File multipartUploadAndGetFile(MultipartUploadFileDto dto) {
|
||||
FileUploadConfig fileUploadConfig = getFileUploadConfig(dto.getAppCode(), dto.getBizScene());
|
||||
private File multipartUploadAndGetFile(MultipartUploadFileDto dto, Integer channelType) {
|
||||
FileUploadConfig fileUploadConfig = getFileUploadConfig(dto.getAppCode(), dto.getBizScene(), channelType);
|
||||
|
||||
// 判断容量
|
||||
String fileConform = isFileConform(fileUploadConfig, (int) dto.getFile().getSize() / 10, dto.getFileName());
|
||||
@ -206,8 +219,8 @@ public class FileServiceImpl implements FileService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileInformationResponse multipartUploadComplete(MultipartUploadCompleteDto dto) {
|
||||
FileUploadConfig fileUploadConfig = getFileUploadConfig(dto.getAppCode(), dto.getBizScene());
|
||||
public FileInformationResponse multipartUploadComplete(MultipartUploadCompleteDto dto, Integer channelType) {
|
||||
FileUploadConfig fileUploadConfig = getFileUploadConfig(dto.getAppCode(), dto.getBizScene(), channelType);
|
||||
// 文件合并并生成 file对象
|
||||
File ossFile = completeFile(fileUploadConfig, dto.getFileName(), dto.getTgtFileKey(),
|
||||
dto.getUploadId(), dto.getPartETags());
|
||||
@ -241,12 +254,12 @@ public class FileServiceImpl implements FileService {
|
||||
return setFileDownloadResponse(file, fileStream);
|
||||
}
|
||||
|
||||
private FileUploadConfig getFileUploadConfig(String appCode, String bizScene) {
|
||||
private FileUploadConfig getFileUploadConfig(String appCode, String bizScene, Integer channelType) {
|
||||
// 检查appCode
|
||||
checkAppCode(appCode);
|
||||
|
||||
// 通过appcode获取文件渠道桶信息
|
||||
AppChannelBucket appChannelBucket = appChannelBucketManager.getByAppCode(appCode);
|
||||
AppChannelBucket appChannelBucket = appChannelBucketManager.getByAppCode(appCode, channelType);
|
||||
|
||||
// 通过渠道桶编码获取到具体文件业务场景
|
||||
FileBusinessScene scene = fileBusinessSceneManager
|
||||
@ -335,12 +348,14 @@ public class FileServiceImpl implements FileService {
|
||||
}
|
||||
}
|
||||
|
||||
private File uploadFileAndGetFile(ServerFileUploadDto dto) {
|
||||
log.info("update fileName:{},appCode:{},bizScene:{}",
|
||||
dto.getFileName(), dto.getAppCode(), dto.getBizScene());
|
||||
FileUploadConfig fileUploadConfig = getFileUploadConfig(dto.getAppCode(), dto.getBizScene());
|
||||
private File uploadFileAndGetFile(ServerFileUploadDto dto, Integer channelType, Integer fileUploadType) {
|
||||
log.info("update channelType:{}, fileName:{}, appCode:{}, bizScene:{}",
|
||||
channelType, dto.getFileName(), dto.getAppCode(), dto.getBizScene());
|
||||
|
||||
FileUploadConfig fileUploadConfig = getFileUploadConfig(dto.getAppCode(), dto.getBizScene(), channelType);
|
||||
|
||||
// 上传文件并生成file对象
|
||||
return generateFile(fileUploadConfig, dto);
|
||||
return generateFile(fileUploadConfig, dto, channelType, fileUploadType);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -479,7 +494,7 @@ public class FileServiceImpl implements FileService {
|
||||
throw new BizException(CodeEnum.APP_CODE_NOT_FOUND);
|
||||
}
|
||||
// 通过appcode获取文件渠道桶信息
|
||||
AppChannelBucket appChannelBucket = appChannelBucketManager.getByAppCode(appCode);
|
||||
AppChannelBucket appChannelBucket = appChannelBucketManager.getByAppCode(appCode, ChannelTypeEnum.OSS.getCode());
|
||||
// 通过渠道桶编码获取到具体文件业务场景
|
||||
FileBusinessScene scene = fileBusinessSceneManager
|
||||
.getByBucketNoAndScene(appChannelBucket.getAppChannelBucketNo(), bizScene);
|
||||
@ -563,19 +578,17 @@ public class FileServiceImpl implements FileService {
|
||||
return fileFormat;
|
||||
}
|
||||
|
||||
private File generateFile(FileUploadConfig fileUploadConfig, ServerFileUploadDto dto) {
|
||||
private File generateFile(FileUploadConfig fileUploadConfig, ServerFileUploadDto dto, Integer channelType,
|
||||
Integer fileUploadType) {
|
||||
|
||||
// 判断容量
|
||||
String fileConform = isFileConform(fileUploadConfig, dto.getFileContent().length,
|
||||
dto.getFileName());
|
||||
|
||||
String fileConform = isFileConform(fileUploadConfig, dto.getFileContent().length, dto.getFileName());
|
||||
String uuid = Utility.getUUID();
|
||||
|
||||
// 生成上传文件的唯一key
|
||||
String tgtFileKey = Utility.generateFileKey(fileUploadConfig.getDirectory(), uuid, fileConform);
|
||||
|
||||
// 上传文件
|
||||
String fileUrl = fileManager.uploadByStream(fileUploadConfig.getBucketName(), tgtFileKey, dto.getFileName(),
|
||||
dto.getAppCode(), dto.getFileContent());
|
||||
dto.getAppCode(), dto.getFileContent(), channelType, fileUploadType, dto.getFilePath());
|
||||
|
||||
// 保存失败
|
||||
if (Utility.isBlank(fileUrl)) {
|
||||
@ -613,4 +626,109 @@ public class FileServiceImpl implements FileService {
|
||||
return resp;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServerFileUploadResponse uploadObs(ServerFileUploadDto dto, ContextInfo.LiteSaasContext liteSaasContext,
|
||||
Integer fileUploadType) {
|
||||
File ossFile = uploadFileAndGetFile(dto, ChannelTypeEnum.OBS.getCode(), fileUploadType);
|
||||
|
||||
//操作日志记录
|
||||
operateLog(dto.toString(), "", OBS_FILE_UPLOAD_CODE, FILE_UPLOAD_NAME, liteSaasContext);
|
||||
return setResponse(ossFile);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFilePath(MultipartFile file) {
|
||||
// 创建输入流
|
||||
InputStream input = null;
|
||||
try {
|
||||
input = file.getInputStream();
|
||||
// 指定目标文件路径及文件名
|
||||
String fileName = file.getOriginalFilename();
|
||||
|
||||
// 生成临时文件名称,防止中文文件名乱码导致删除失败
|
||||
assert fileName != null;
|
||||
String tempFileName = Utility.getUUID() + fileName.substring(fileName.lastIndexOf("."));
|
||||
|
||||
// 获取操作系统名称,不同操作系统中文件路径有区别
|
||||
String osName = System.getProperty("os.name");
|
||||
String rootDir;
|
||||
// linux操作系统
|
||||
if (Objects.nonNull(osName) && osName.toLowerCase().startsWith("linux")) {
|
||||
rootDir = "/mnt/temp/obs";
|
||||
} else {
|
||||
// 其它操作系统
|
||||
ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
|
||||
String classPath = Objects.requireNonNull(contextClassLoader.getResource("")).getPath();
|
||||
rootDir = classPath.substring(0, classPath.indexOf("/target/classes/"));
|
||||
}
|
||||
|
||||
// 拼接文件路径
|
||||
String filePath = rootDir + SEPARATOR + "temp_directory";
|
||||
String absolutePath = filePath + SEPARATOR + tempFileName;
|
||||
|
||||
// 创建临时文件夹
|
||||
java.io.File tempDirectory = new java.io.File(filePath);
|
||||
if (!tempDirectory.exists()) {
|
||||
boolean flag = tempDirectory.mkdirs();
|
||||
if (flag) {
|
||||
log.info("临时文件夹创建成功,{}", flag);
|
||||
} else {
|
||||
log.info("临时文件夹创建失败,{}", flag);
|
||||
// 兜底
|
||||
absolutePath = rootDir + SEPARATOR + tempFileName;
|
||||
}
|
||||
}
|
||||
log.info("临时文件绝对路径:{}", absolutePath);
|
||||
|
||||
// 创建输出流并写入数据
|
||||
OutputStream output = Files.newOutputStream(Paths.get(absolutePath));
|
||||
byte[] buffer = new byte[1024];
|
||||
int length;
|
||||
while ((length = input.read(buffer)) > 0) {
|
||||
output.write(buffer, 0, length);
|
||||
}
|
||||
|
||||
// 关闭流
|
||||
input.close();
|
||||
output.close();
|
||||
|
||||
return absolutePath;
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public ServerFileDownloadResponse getObject(ServerFileDownloadDto dto, Integer fileDownloadType) {
|
||||
log.info("obs download file = {}", JsonUtil.obj2Str(dto));
|
||||
File file = null;
|
||||
String fileKey = dto.getFileKey();
|
||||
if (fileKey.contains(IS_URL)) {
|
||||
String urlMd5 = Utility.getMd5(fileKey);
|
||||
file = fileDao.getByUrlMd5(urlMd5);
|
||||
} else {
|
||||
file = fileDao.getByFileUuid(fileKey);
|
||||
}
|
||||
if (Utility.objIsNull(file)) {
|
||||
log.warn("obs download file is null, fileKey = {}", fileKey);
|
||||
BizException.error(false, CodeEnum.FILE_NOT_FOUND);
|
||||
}
|
||||
|
||||
// 对象名称:目录+文件名
|
||||
String objectKey = file.getDirectory() + SEPARATOR + file.getFileName();
|
||||
// 桶名称
|
||||
String bucketName = file.getBucketName();
|
||||
InputStream fileStream = null;
|
||||
String tempUrlFromOns = null;
|
||||
if (FileDownloadTypeEnum.TEMPORARY_URL_ACCESS.getCode().equals(fileDownloadType)) {
|
||||
tempUrlFromOns = fileManager.getTempUrlFromOns(bucketName, objectKey);
|
||||
} else {
|
||||
fileStream = fileManager.downloadObsFile(bucketName, objectKey, fileDownloadType);
|
||||
if (Objects.isNull(fileStream)) {
|
||||
log.warn("下载的文件流为空");
|
||||
}
|
||||
}
|
||||
ServerFileDownloadResponse response = setFileDownloadResponse(file, fileStream);
|
||||
response.setSignedUrl(tempUrlFromOns);
|
||||
return response;
|
||||
}
|
||||
}
|
||||
|
||||
6
pom.xml
6
pom.xml
@ -21,6 +21,7 @@
|
||||
<axzo-dependencies.version>2.0.0-SNAPSHOT</axzo-dependencies.version>
|
||||
<aliyun-oss.version>3.10.2</aliyun-oss.version>
|
||||
<axzo-log-api.version>1.0.0-SNAPSHOT</axzo-log-api.version>
|
||||
<huaiweicloud-obs.versiion>3.23.3</huaiweicloud-obs.versiion>
|
||||
</properties>
|
||||
|
||||
<modules>
|
||||
@ -101,6 +102,11 @@
|
||||
<artifactId>axzo-log-api</artifactId>
|
||||
<version>${axzo-log-api.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.huaweicloud</groupId>
|
||||
<artifactId>esdk-obs-java-bundle</artifactId>
|
||||
<version>${huaiweicloud-obs.versiion}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user