fix(*) 首次提交ResourceManager项目
This commit is contained in:
145
ResourceManager/pom.xml
Normal file
145
ResourceManager/pom.xml
Normal file
@ -0,0 +1,145 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>cn.crtech.cloud.resource_manager</groupId>
|
||||
<artifactId>ResourceManager</artifactId>
|
||||
<version>1.0.1</version>
|
||||
|
||||
<!-- 父工程 -->
|
||||
<parent>
|
||||
<groupId>cn.crtech.cloud.dependencies</groupId>
|
||||
<artifactId>Dependencies</artifactId>
|
||||
<version>1.0.1</version>
|
||||
<relativePath/>
|
||||
</parent>
|
||||
|
||||
<!-- 依赖的版本锁定 -->
|
||||
<properties>
|
||||
<maven.compiler.source>8</maven.compiler.source>
|
||||
<maven.compiler.target>8</maven.compiler.target>
|
||||
<java.version>1.8</java.version>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
|
||||
<aliyun.oss.version>3.13.2</aliyun.oss.version>
|
||||
<minio.version>7.0.2</minio.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
<!-- 使用launcher启动时放开 begin-->
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-tomcat</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
<!-- 使用launcher启动时放开 end-->
|
||||
</dependency>
|
||||
|
||||
<!-- 使用launcher启动时放开 begin -->
|
||||
<dependency>
|
||||
<groupId>org.apache.tomcat.embed</groupId>
|
||||
<artifactId>tomcat-embed-jasper</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>javax.servlet-api</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- 使用launcher启动时放开 end -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-validation</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-configuration-processor</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<!-- nacos 客户端-->
|
||||
<dependency>
|
||||
<groupId>com.alibaba.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- 微服务RPC调用 -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-openfeign</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- 热部署 -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-devtools</artifactId>
|
||||
<optional>true</optional> <!-- 这个需要为 true 热部署才有效 -->
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-redis</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>io.lettuce</groupId>
|
||||
<artifactId>lettuce-core</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>redis.clients</groupId>
|
||||
<artifactId>jedis</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-test</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-lang3</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>cn.crtech.cloud.common</groupId>
|
||||
<artifactId>Common</artifactId>
|
||||
<version>1.0.1</version>
|
||||
</dependency>
|
||||
|
||||
<!--阿里云oss-->
|
||||
<dependency>
|
||||
<groupId>com.aliyun.oss</groupId>
|
||||
<artifactId>aliyun-sdk-oss</artifactId>
|
||||
<version>${aliyun.oss.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!--minio-->
|
||||
<dependency>
|
||||
<groupId>io.minio</groupId>
|
||||
<artifactId>minio</artifactId>
|
||||
<version>${minio.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
<configuration>
|
||||
<fork>true</fork>
|
||||
<jvmArguments>-Dfile.encoding=UTF-8</jvmArguments>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
@ -0,0 +1,33 @@
|
||||
package cn.crtech.cloud.resmanager;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
|
||||
import tk.mybatis.spring.annotation.MapperScan;
|
||||
|
||||
//微服务启动时使用 begin
|
||||
|
||||
@EnableDiscoveryClient
|
||||
@SpringBootApplication
|
||||
@MapperScan("cn.crtech.cloud.resmanager.mapper")
|
||||
public class ResmanagerApplcation {
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(ResmanagerApplcation.class, args);
|
||||
}
|
||||
}
|
||||
|
||||
//微服务启动时使用 end
|
||||
|
||||
//使用launcher启动时使用 begin
|
||||
//launcher.NacosConfig @Component需要放开
|
||||
//
|
||||
//@SpringBootApplication
|
||||
//@MapperScan("cn.crtech.cloud.resmanager.mapper")
|
||||
//public class ResmanagerApplcation extends SpringBootServletInitializer {
|
||||
// @Override
|
||||
// protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
|
||||
// return application.sources(ResmanagerApplcation.class);
|
||||
// }
|
||||
//}
|
||||
|
||||
//使用launcher启动时使用 end
|
||||
@ -0,0 +1,18 @@
|
||||
package cn.crtech.cloud.resmanager.config;
|
||||
|
||||
import lombok.Data;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Data
|
||||
@Component
|
||||
@ConfigurationProperties(prefix = "resmanager.aliyunoss")
|
||||
public class AliYunOSSConfig {
|
||||
private String serverUrl;
|
||||
|
||||
private String accessKey;
|
||||
|
||||
private String secretKey;
|
||||
|
||||
private String bucketName;
|
||||
}
|
||||
@ -0,0 +1,14 @@
|
||||
package cn.crtech.cloud.resmanager.config;
|
||||
|
||||
import lombok.Data;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Data
|
||||
@Component
|
||||
@ConfigurationProperties(prefix = "resmanager.local")
|
||||
public class LocalConfig {
|
||||
private String path;
|
||||
|
||||
private String bucketName;
|
||||
}
|
||||
@ -0,0 +1,26 @@
|
||||
package cn.crtech.cloud.resmanager.config;
|
||||
|
||||
import lombok.Data;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Data
|
||||
@Component
|
||||
@ConfigurationProperties(prefix = "resmanager.minio")
|
||||
public class MinioConfig {
|
||||
private String endpoint;
|
||||
|
||||
private Integer port;
|
||||
|
||||
private String accessKey;
|
||||
|
||||
private String secretKey;
|
||||
|
||||
private String bucketName;
|
||||
|
||||
private Boolean secure;
|
||||
|
||||
private String accessType;
|
||||
|
||||
private Integer urlExpires;
|
||||
}
|
||||
@ -0,0 +1,30 @@
|
||||
package cn.crtech.cloud.resmanager.config;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.redis.connection.RedisConnectionFactory;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.data.redis.repository.configuration.EnableRedisRepositories;
|
||||
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
|
||||
import org.springframework.data.redis.serializer.StringRedisSerializer;
|
||||
|
||||
/**
|
||||
* Redis相关配置
|
||||
*/
|
||||
@Configuration
|
||||
@EnableRedisRepositories
|
||||
public class RedisRepositoryConfig {
|
||||
@Bean
|
||||
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
|
||||
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
|
||||
redisTemplate.setConnectionFactory(connectionFactory);
|
||||
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
|
||||
redisTemplate.setKeySerializer(stringRedisSerializer);
|
||||
redisTemplate.setHashKeySerializer(stringRedisSerializer);
|
||||
Jackson2JsonRedisSerializer<?> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
|
||||
redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
|
||||
redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);
|
||||
redisTemplate.afterPropertiesSet();
|
||||
return redisTemplate;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,181 @@
|
||||
package cn.crtech.cloud.resmanager.controller;
|
||||
|
||||
import cn.crtech.cloud.common.api.CommonResult;
|
||||
import cn.crtech.cloud.common.utils.ThumbnailatorUtil;
|
||||
import cn.hutool.core.util.IdUtil;
|
||||
import cn.hutool.json.JSONObject;
|
||||
import com.aliyun.oss.OSS;
|
||||
import com.aliyun.oss.OSSClientBuilder;
|
||||
import com.aliyun.oss.model.ObjectMetadata;
|
||||
import com.aliyun.oss.model.PutObjectResult;
|
||||
import io.minio.MinioClient;
|
||||
import io.minio.PutObjectOptions;
|
||||
import io.minio.errors.*;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import org.springframework.web.multipart.MultipartHttpServletRequest;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Author : yj
|
||||
* Date : 2021-03-19
|
||||
* Description:
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/file")
|
||||
public class FileController {
|
||||
private static String endpoint = "http://oss-cn-chengdu.aliyuncs.com";
|
||||
private static String accessKeyId = "LTAI5tGBETbnyAS6tAxULF8M";
|
||||
private static String accessKeySecret = "lJppRT678UVMWJr9EBaJfbKdoZ7eBl";
|
||||
private static String bucketName = "crtechtest";
|
||||
|
||||
@RequestMapping("/u1")
|
||||
public CommonResult uploadFileTOALiYUN(HttpServletRequest request, HttpServletResponse response) {
|
||||
OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
|
||||
List<MultipartFile> files = ((MultipartHttpServletRequest) request).getFiles("file");
|
||||
files.stream().forEach(file -> {
|
||||
System.out.println(file.getOriginalFilename());
|
||||
//System.out.println(file.getBytes());
|
||||
System.out.println(file.getName());
|
||||
System.out.println(file.getContentType());
|
||||
System.out.println(file.getSize());
|
||||
String fileKey = file.getOriginalFilename();
|
||||
System.out.println();
|
||||
try {
|
||||
ObjectMetadata objectMetadata = new ObjectMetadata();
|
||||
objectMetadata.setContentType("image/jpg");
|
||||
|
||||
PutObjectResult putObjectResult = ossClient.putObject(bucketName, fileKey, file.getResource().getInputStream(), objectMetadata);
|
||||
// 设置URL过期时间为10年 3600l* 1000*24*365*10
|
||||
Date expiration = new Date(new Date().getTime() + 3600l * 1000 * 24 * 365 * 10);
|
||||
URL url = ossClient.generatePresignedUrl(bucketName, fileKey, expiration);
|
||||
|
||||
|
||||
System.out.println(putObjectResult.getETag());
|
||||
System.out.println(putObjectResult.getVersionId());
|
||||
System.out.println(putObjectResult.getRequestId());
|
||||
System.out.println(putObjectResult.getServerCRC());
|
||||
System.out.println(url);
|
||||
|
||||
|
||||
} catch (IOException e) {
|
||||
ossClient.shutdown();
|
||||
e.printStackTrace();
|
||||
}
|
||||
ossClient.shutdown();
|
||||
|
||||
});
|
||||
|
||||
|
||||
return CommonResult.success(null);
|
||||
}
|
||||
|
||||
@RequestMapping("/u")
|
||||
public CommonResult uploadFileTOMINIO(HttpServletRequest request, HttpServletResponse response) throws Exception {
|
||||
|
||||
try {
|
||||
// 使用MinIO服务的URL,端口,Access key和Secret key创建一个MinioClient对象
|
||||
MinioClient minioClient = new MinioClient("http://localhost:9000", "minio", "KWbPmRsTWre2X2X6");
|
||||
|
||||
String bucketName = "bucket1";
|
||||
// 检查存储桶是否已经存在
|
||||
boolean isExist = minioClient.bucketExists(bucketName);
|
||||
if (isExist) {
|
||||
System.out.println("Bucket already exists.");
|
||||
} else {
|
||||
// 创建一个名为asiatrip的存储桶,用于存储照片的zip文件。
|
||||
minioClient.makeBucket(bucketName);
|
||||
JSONObject jsonObject = new JSONObject();
|
||||
ArrayList<Map<String, Object>> object = new ArrayList<Map<String, Object>>();
|
||||
Map<String, Object> Map1 = new HashMap<>();
|
||||
String[] str = new String[]{"s3:GetBucketLocation", "s3:ListBucket"};
|
||||
Map1.put("Action", str);
|
||||
Map1.put("Effect", "Allow");
|
||||
Map1.put("Principal", "*");
|
||||
Map1.put("Resource", "arn:aws:s3:::" + bucketName);
|
||||
object.add(Map1);
|
||||
Map<String, Object> Map2 = new HashMap<>();
|
||||
Map2.put("Action", "s3:GetObject");
|
||||
Map2.put("Effect", "Allow");
|
||||
Map2.put("Principal", "*");
|
||||
Map2.put("Resource", "arn:aws:s3:::" + bucketName + "/myobject*");
|
||||
object.add(Map2);
|
||||
jsonObject.set("Statement", object);
|
||||
jsonObject.set("Version", "2012-10-17");
|
||||
String policyJson = jsonObject.toString();
|
||||
minioClient.setBucketPolicy(bucketName, policyJson);
|
||||
}
|
||||
|
||||
String bucketPolicy = minioClient.getBucketPolicy(bucketName);
|
||||
|
||||
System.out.println(bucketPolicy);
|
||||
|
||||
|
||||
List<MultipartFile> files = ((MultipartHttpServletRequest) request).getFiles("file");
|
||||
String objectUrl = null;
|
||||
for (MultipartFile file : files) {
|
||||
//InputStream inputStream1 = file.getInputStream();
|
||||
String fileKey = file.getOriginalFilename();
|
||||
String fileType = fileKey.split(".")[1];
|
||||
System.out.println(fileKey);
|
||||
//System.out.println(file.getBytes());
|
||||
System.out.println(file.getName());
|
||||
System.out.println(file.getContentType());
|
||||
System.out.println(file.getSize());
|
||||
PutObjectOptions putObjectOptions = new PutObjectOptions(-1, 5L * 1024 * 1024);
|
||||
putObjectOptions.setContentType("image/jpeg;charset=UTF-8");
|
||||
// putObjectOptions.setContentType();
|
||||
// putObjectOptions.setHeaders();
|
||||
|
||||
// 使用putObject上传一个文件到存储桶中。
|
||||
|
||||
try {
|
||||
|
||||
InputStream inputStream = file.getResource().getInputStream();
|
||||
|
||||
byte[] bytes = ThumbnailatorUtil.compressImageWithWH(file.getBytes(), 256, 256);
|
||||
|
||||
minioClient.putObject(bucketName, IdUtil.simpleUUID() + "." + fileType, inputStream, putObjectOptions);
|
||||
objectUrl = minioClient.getObjectUrl(bucketName, fileKey);
|
||||
System.out.println("====objectUrl===" + objectUrl);
|
||||
} catch (ErrorResponseException e) {
|
||||
e.printStackTrace();
|
||||
} catch (InsufficientDataException e) {
|
||||
e.printStackTrace();
|
||||
} catch (InternalException e) {
|
||||
e.printStackTrace();
|
||||
} catch (InvalidBucketNameException e) {
|
||||
e.printStackTrace();
|
||||
} catch (InvalidKeyException e) {
|
||||
e.printStackTrace();
|
||||
} catch (InvalidResponseException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
e.printStackTrace();
|
||||
} catch (XmlParserException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
// files.stream().forEach(file -> {
|
||||
//
|
||||
//
|
||||
// });
|
||||
Map<String, Object> retMap = new HashMap<>();
|
||||
retMap.put("url", objectUrl);
|
||||
return CommonResult.success(retMap);
|
||||
} catch (Exception e) {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,242 @@
|
||||
package cn.crtech.cloud.resmanager.controller;
|
||||
|
||||
import cn.crtech.cloud.common.api.CommonResult;
|
||||
import cn.crtech.cloud.common.dto.Result;
|
||||
import cn.crtech.cloud.resmanager.pojo.Resource;
|
||||
import cn.crtech.cloud.resmanager.service.ResourceService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URLDecoder;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/")
|
||||
public class ResourceController {
|
||||
@Autowired
|
||||
private ResourceService service;
|
||||
|
||||
@PostMapping("/list")
|
||||
public CommonResult list(@RequestBody List<String> fileIds) throws Exception {
|
||||
List<Resource> resources = service.listByIds(fileIds);
|
||||
return CommonResult.success(resources);
|
||||
}
|
||||
|
||||
@PostMapping("/remove")
|
||||
public CommonResult remove(@RequestBody List<String> fileIds) throws Exception {
|
||||
return CommonResult.success(service.remove(fileIds));
|
||||
}
|
||||
|
||||
@PostMapping("/commit")
|
||||
public CommonResult commit(@RequestBody List<String> fileIds) throws Exception {
|
||||
return CommonResult.success(service.commit(fileIds));
|
||||
}
|
||||
|
||||
@PostMapping("/rollback")
|
||||
public CommonResult rollback(@RequestBody List<String> fileIds) throws Exception {
|
||||
return CommonResult.success(service.rollback(fileIds));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取文件实际显示访问url
|
||||
*
|
||||
* @param fileId 文件ID
|
||||
* @param response 返回结果
|
||||
* @throws Exception 文件不存在/解析异常
|
||||
*/
|
||||
@GetMapping("/s/{fileId}")
|
||||
public void showUrl(@PathVariable(value = "fileId") String fileId,
|
||||
final HttpServletResponse response) throws Exception {
|
||||
// return CommonResult.success(service.getUrl(fileId, false));
|
||||
response.sendRedirect(service.getUrl(fileId, false));
|
||||
}
|
||||
|
||||
@GetMapping("/getUrl/{fileId}")
|
||||
public CommonResult getUrl(@PathVariable(value = "fileId") String fileId,
|
||||
final HttpServletResponse response) throws Exception {
|
||||
return CommonResult.success(service.getUrl(fileId, false));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param params 参数
|
||||
* <ul>
|
||||
* <li>list: 文件ID集合</li>
|
||||
* </ul>
|
||||
* @return 返回查询结果
|
||||
*/
|
||||
@PostMapping("/s/much")
|
||||
public CommonResult showMuchUrl(@RequestBody Map<String, Object> params) throws Exception {
|
||||
List<String> list = (List<String>) params.get("list");
|
||||
if (list.size() > 0) {
|
||||
return CommonResult.success(service.getMuchUrl(list, false));
|
||||
} else {
|
||||
return CommonResult.failed("参数为空");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取文件实际下载url
|
||||
*
|
||||
* @param fileId 文件ID
|
||||
* @param response 返回数据对象集合
|
||||
* @throws Exception 可能存在文件不存在等异常
|
||||
*/
|
||||
@GetMapping("/d/{fileId}")
|
||||
public void downloadUrl(@PathVariable(value = "fileId") String fileId,
|
||||
final HttpServletResponse response) throws Exception {
|
||||
response.sendRedirect(service.getUrl(fileId, true));
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用本地链接访问时显示或下载文件流
|
||||
* 本地存储时:最后建议使用nginx做转发
|
||||
* TODO: MinIO和AliYunOSS时由于要获取流,可能要考虑做二级资源缓存,然后使用nginx做转发
|
||||
*
|
||||
* @param contentType1
|
||||
* @param contentType2
|
||||
* @param request
|
||||
* @param response
|
||||
* @return
|
||||
* @throws Exception
|
||||
* @Params ** path: /ls/erp/prescription/202305111110183b5464d7ce964493a1e0a7714109cc48
|
||||
*/
|
||||
@GetMapping({"/res/{contentType1}/{contentType2}/**", "/down/{contentType1}/{contentType2}/**"})
|
||||
public ResponseEntity<StreamingResponseBody> getSteam(
|
||||
@PathVariable(value = "contentType1") String contentType1,
|
||||
@PathVariable(value = "contentType2") String contentType2,
|
||||
final HttpServletRequest request,
|
||||
final HttpServletResponse response) throws Exception {
|
||||
|
||||
boolean download = request.getRequestURI().startsWith("/down");
|
||||
|
||||
response.setContentType(contentType1 + "/" + contentType2);
|
||||
if (download) {
|
||||
response.setHeader("Content-Disposition", "attachment");
|
||||
}
|
||||
|
||||
String relativePath = "/" + URLDecoder.decode(request.getRequestURI().substring(((download ? "/down/" : "/res/") + contentType1 + "/" + contentType2 + "/").length()), "UTF-8");
|
||||
|
||||
StreamingResponseBody stream = outputStream -> {
|
||||
InputStream inputStream = null;
|
||||
try {
|
||||
inputStream = service.getStreamByPath(relativePath);
|
||||
byte[] bytes = new byte[1024];
|
||||
int len;
|
||||
while ((len = inputStream.read(bytes)) != -1) {
|
||||
outputStream.write(bytes, 0, len);
|
||||
}
|
||||
outputStream.flush();
|
||||
} catch (Exception e) {
|
||||
throw new IOException(e);
|
||||
} finally {
|
||||
if (inputStream != null) inputStream.close();
|
||||
if (outputStream != null) outputStream.close();
|
||||
}
|
||||
};
|
||||
return new ResponseEntity(stream, HttpStatus.OK);
|
||||
}
|
||||
|
||||
@PostMapping("/upload")
|
||||
public CommonResult addFile(
|
||||
@RequestParam(name = "file") MultipartFile file,
|
||||
@RequestParam(name = "path") String path,
|
||||
@RequestParam(name = "name") String name,
|
||||
@RequestParam(name = "description") String description) throws Exception {
|
||||
Resource resource = service.addFile(file, path, name, description);
|
||||
return CommonResult.success(resource);
|
||||
}
|
||||
|
||||
/**
|
||||
* 拷贝文件
|
||||
*
|
||||
* @param fileId
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
@GetMapping("/copyOfMinIoFile")
|
||||
public Result copyOfMinIoFile(@RequestParam("fileId") String fileId) throws Exception {
|
||||
return Result.success(service.copyOfMinIoFile(fileId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过文件id获取文件流
|
||||
*
|
||||
* @param fileId
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/getFileStream")
|
||||
public ResponseEntity<StreamingResponseBody> getFileStream(@RequestParam("fileId") String fileId) {
|
||||
StreamingResponseBody stream = outputStream -> {
|
||||
InputStream inputStream = null;
|
||||
try {
|
||||
inputStream = service.getStreamByFileId(fileId);
|
||||
byte[] bytes = new byte[1024];
|
||||
int len;
|
||||
while ((len = inputStream.read(bytes)) != -1) {
|
||||
outputStream.write(bytes, 0, len);
|
||||
}
|
||||
outputStream.flush();
|
||||
} catch (Exception e) {
|
||||
throw new IOException(e);
|
||||
} finally {
|
||||
if (inputStream != null) inputStream.close();
|
||||
outputStream.close();
|
||||
}
|
||||
};
|
||||
return new ResponseEntity(stream, HttpStatus.OK);
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用本地链接访问时显示或下载文件流
|
||||
* 本地存储时:最后建议使用nginx做转发
|
||||
* TODO: MinIO和AliYunOSS时由于要获取流,可能要考虑做二级资源缓存,然后使用nginx做转发
|
||||
*
|
||||
* @param request
|
||||
* @param response
|
||||
* @return
|
||||
* @throws Exception
|
||||
* @Params ** path: /ls/erp/prescription/202305111110183b5464d7ce964493a1e0a7714109cc48
|
||||
*/
|
||||
@GetMapping({"/byte/res/stream/{fileId}", "/byte/down/stream/{fileId}"})
|
||||
public CommonResult getFileStreamByteByFileId(
|
||||
@PathVariable(name = "fileId") String fileId,
|
||||
final HttpServletRequest request,
|
||||
final HttpServletResponse response) throws Exception {
|
||||
boolean download = request.getRequestURI().startsWith("/down");
|
||||
if (download) {
|
||||
response.setHeader("Content-Disposition", "attachment");
|
||||
}
|
||||
Resource resource = service.get(fileId);
|
||||
String relativePath = URLDecoder.decode(resource.getPath() + "/" + resource.getName(), "UTF-8");
|
||||
InputStream inputStream = service.getStreamByPath(relativePath);
|
||||
try {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
byte[] buffer = new byte[1024];
|
||||
int num = inputStream.read(buffer);
|
||||
while (num != -1) {
|
||||
baos.write(buffer, 0, num);
|
||||
num = inputStream.read(buffer);
|
||||
}
|
||||
baos.flush();
|
||||
Map<String, Object> fileMap = new HashMap<>();
|
||||
fileMap.put("fileByteArray", baos.toByteArray());
|
||||
return CommonResult.success(fileMap, "获取成功");
|
||||
} finally {
|
||||
if (inputStream != null) {
|
||||
inputStream.close();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,14 @@
|
||||
package cn.crtech.cloud.resmanager.general;
|
||||
|
||||
import cn.crtech.cloud.common.api.CommonResult;
|
||||
import org.springframework.cloud.openfeign.FeignClient;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@FeignClient("crtech-cloud-general")
|
||||
public interface UserController {
|
||||
@RequestMapping("/user/info")
|
||||
CommonResult getUserInfo(@RequestBody Map<String, String> map);
|
||||
}
|
||||
@ -0,0 +1,42 @@
|
||||
package cn.crtech.cloud.resmanager.holder;
|
||||
|
||||
import cn.crtech.cloud.common.dto.UserDto;
|
||||
import cn.hutool.core.convert.Convert;
|
||||
import cn.hutool.json.JSONObject;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.context.request.RequestContextHolder;
|
||||
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLDecoder;
|
||||
|
||||
/**
|
||||
* 获取登录用户信息
|
||||
* Created by macro on 2020/6/17.
|
||||
*/
|
||||
@Component
|
||||
public class LoginUserHolder {
|
||||
public UserDto getCurrentUser() {
|
||||
//从Header中获取用户信息
|
||||
ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
|
||||
HttpServletRequest request = servletRequestAttributes.getRequest();
|
||||
String userStr = null;
|
||||
UserDto userDto = new UserDto();
|
||||
try {
|
||||
if (!StringUtils.isBlank(request.getHeader("user"))) {
|
||||
userStr = URLDecoder.decode(request.getHeader("user"), "UTF-8");
|
||||
JSONObject userJsonObject = new JSONObject(userStr);
|
||||
userDto.setCompanyCode(userJsonObject.getStr("company_code"));
|
||||
userDto.setUserName(userJsonObject.getStr("user_name"));
|
||||
userDto.setId(Integer.valueOf(userJsonObject.getStr("id")));
|
||||
userDto.setRoles(Convert.toList(String.class, userJsonObject.get("authorities")));
|
||||
return userDto;
|
||||
}
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,10 @@
|
||||
package cn.crtech.cloud.resmanager.mapper;
|
||||
|
||||
import cn.crtech.cloud.resmanager.pojo.Resource;
|
||||
import org.springframework.stereotype.Repository;
|
||||
import tk.mybatis.mapper.additional.idlist.SelectByIdListMapper;
|
||||
import tk.mybatis.mapper.common.Mapper;
|
||||
|
||||
@Repository
|
||||
public interface ResourceMapper extends Mapper<Resource>, SelectByIdListMapper<Resource, String> {
|
||||
}
|
||||
@ -0,0 +1,46 @@
|
||||
package cn.crtech.cloud.resmanager.pojo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import javax.persistence.*;
|
||||
import java.util.Date;
|
||||
|
||||
@Data
|
||||
@Table(name = "resources")
|
||||
public class Resource {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY, generator = "select uuid()")
|
||||
private String id;
|
||||
|
||||
@Column(name = "mime_type")
|
||||
private String mimeType;
|
||||
@Column(name = "name")
|
||||
private String name;
|
||||
@Column(name = "size")
|
||||
private Long size;
|
||||
@Column(name = "path")
|
||||
private String path;
|
||||
@Column(name = "description")
|
||||
private String description;
|
||||
@Column(name = "create_time")
|
||||
private Date createTime;
|
||||
@Column(name = "create_user")
|
||||
private Integer createUser;
|
||||
@Column(name = "last_modify_time")
|
||||
private Date lastModifyTime;
|
||||
@Column(name = "last_modify_user")
|
||||
private Integer lastModifyUser;
|
||||
@Column(name = "is_temp")
|
||||
private Integer isTemp;
|
||||
|
||||
/**
|
||||
* 1 插入
|
||||
* 2 修改(基本没用)
|
||||
* 3 删除
|
||||
*/
|
||||
@Column(name = "temp_oper")
|
||||
private Integer tempOper;
|
||||
|
||||
@Transient
|
||||
private String url;
|
||||
}
|
||||
@ -0,0 +1,74 @@
|
||||
package cn.crtech.cloud.resmanager.server;
|
||||
|
||||
import cn.crtech.cloud.resmanager.pojo.Resource;
|
||||
import cn.crtech.cloud.resmanager.server.impl.AliYunOSSStorage;
|
||||
import cn.crtech.cloud.resmanager.server.impl.LocalStorage;
|
||||
import cn.crtech.cloud.resmanager.server.impl.MinioStorage;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.ApplicationArguments;
|
||||
import org.springframework.boot.ApplicationRunner;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.io.InputStream;
|
||||
|
||||
@Component
|
||||
public class ResmanagerServer implements ApplicationRunner {
|
||||
@Value("${resmanager.type}")
|
||||
private String type;
|
||||
|
||||
private Storage storage;
|
||||
|
||||
@Autowired
|
||||
LocalStorage local;
|
||||
|
||||
@Autowired
|
||||
MinioStorage minio;
|
||||
|
||||
@Autowired
|
||||
AliYunOSSStorage aliYunOSS;
|
||||
|
||||
@Override
|
||||
public void run(ApplicationArguments args) throws Exception {
|
||||
initStorage();
|
||||
}
|
||||
|
||||
private void initStorage() throws Exception {
|
||||
if (local.getType().equals(type)) {
|
||||
storage = local;
|
||||
} else if (minio.getType().equals(type)) {
|
||||
storage = minio;
|
||||
} else if (aliYunOSS.getType().equals(type)) {
|
||||
storage = aliYunOSS;
|
||||
} else {
|
||||
throw new Exception("unknown storage type: " + type);
|
||||
}
|
||||
storage.init();
|
||||
}
|
||||
|
||||
public String getUrl(@NotNull Resource file, boolean download) throws Exception {
|
||||
return storage.getUrl(file, download);
|
||||
}
|
||||
|
||||
public InputStream getStream(String relativePath) throws Exception {
|
||||
return storage.getStream(relativePath);
|
||||
}
|
||||
|
||||
public InputStream getStreamByResource(Resource resource) throws Exception {
|
||||
return storage.getStream(resource.getPath() + "/" + resource.getName());
|
||||
}
|
||||
|
||||
public void store(Resource resource, MultipartFile file) throws Exception {
|
||||
storage.store(resource, file);
|
||||
}
|
||||
|
||||
public void remove(Resource file) throws Exception {
|
||||
storage.remove(file);
|
||||
}
|
||||
|
||||
public long getExpireTime() {
|
||||
return storage.getExpireTime();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,23 @@
|
||||
package cn.crtech.cloud.resmanager.server;
|
||||
|
||||
import cn.crtech.cloud.resmanager.pojo.Resource;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.io.InputStream;
|
||||
|
||||
public interface Storage {
|
||||
String getType();
|
||||
|
||||
void init() throws Exception;
|
||||
|
||||
String getUrl(@NotNull Resource file, boolean download) throws Exception;
|
||||
|
||||
InputStream getStream(String relativePath) throws Exception;
|
||||
|
||||
void store(Resource resource, MultipartFile file) throws Exception;
|
||||
|
||||
void remove(Resource file) throws Exception;
|
||||
|
||||
long getExpireTime();
|
||||
}
|
||||
@ -0,0 +1,50 @@
|
||||
package cn.crtech.cloud.resmanager.server.impl;
|
||||
|
||||
import cn.crtech.cloud.resmanager.config.AliYunOSSConfig;
|
||||
import cn.crtech.cloud.resmanager.pojo.Resource;
|
||||
import cn.crtech.cloud.resmanager.server.Storage;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.io.InputStream;
|
||||
|
||||
@Component
|
||||
public class AliYunOSSStorage implements Storage {
|
||||
@Autowired
|
||||
private AliYunOSSConfig config;
|
||||
|
||||
@Override
|
||||
public String getType() {
|
||||
return "aliyunoss";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() throws Exception {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUrl(Resource file, boolean download) throws Exception {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream getStream(String relativePath) throws Exception {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void store(Resource resource, MultipartFile file) throws Exception {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove(Resource file) throws Exception {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getExpireTime() {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,100 @@
|
||||
package cn.crtech.cloud.resmanager.server.impl;
|
||||
|
||||
import cn.crtech.cloud.resmanager.config.LocalConfig;
|
||||
import cn.crtech.cloud.resmanager.pojo.Resource;
|
||||
import cn.crtech.cloud.resmanager.server.Storage;
|
||||
import cn.hutool.core.util.ArrayUtil;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URLEncoder;
|
||||
|
||||
@Component
|
||||
public class LocalStorage implements Storage {
|
||||
@Autowired
|
||||
private LocalConfig config;
|
||||
|
||||
@Override
|
||||
public String getType() {
|
||||
return "local";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() throws Exception {
|
||||
File file = new File(config.getPath(), config.getBucketName());
|
||||
if (!file.exists()) {
|
||||
file.mkdirs();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUrl(Resource file, boolean download) throws Exception {
|
||||
String[] split = file.getPath().split("/");
|
||||
for (int i = 0; i < split.length; i++) {
|
||||
split[i] = URLEncoder.encode(split[i], "UTF-8");
|
||||
}
|
||||
String path = "/" + ArrayUtil.join(split, "/") + "/" + URLEncoder.encode(file.getName(), "UTF-8");
|
||||
if (download) {
|
||||
return "/down/" + file.getMimeType() + path;
|
||||
} else {
|
||||
return "/res/" + file.getMimeType() + path;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream getStream(String relativePath) throws Exception {
|
||||
File file = new File(config.getPath(), config.getBucketName());
|
||||
if (!file.exists()) {
|
||||
file.mkdirs();
|
||||
}
|
||||
file = new File(file, relativePath);
|
||||
if (!file.exists()) {
|
||||
throw new FileNotFoundException(file.getAbsolutePath());
|
||||
}
|
||||
return new FileInputStream(file);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void store(Resource resource, MultipartFile file) throws Exception {
|
||||
File f = new File(config.getPath(), config.getBucketName());
|
||||
if (!f.exists()) {
|
||||
f.mkdirs();
|
||||
}
|
||||
f = new File(f, resource.getPath().substring(1));
|
||||
if (!f.exists()) {
|
||||
f.mkdirs();
|
||||
}
|
||||
f = new File(f, resource.getName());
|
||||
if (f.exists()) {
|
||||
throw new Exception("文件已存在");
|
||||
}
|
||||
file.transferTo(f);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove(Resource file) throws Exception {
|
||||
File f = new File(config.getPath(), config.getBucketName());
|
||||
if (!f.exists()) {
|
||||
f.mkdirs();
|
||||
}
|
||||
f = new File(f, file.getPath().substring(1));
|
||||
if (!f.exists()) {
|
||||
f.mkdirs();
|
||||
}
|
||||
f = new File(f, file.getName());
|
||||
if (f.exists()) {
|
||||
f.delete();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getExpireTime() {
|
||||
return 60 * 60;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,118 @@
|
||||
package cn.crtech.cloud.resmanager.server.impl;
|
||||
|
||||
import cn.crtech.cloud.resmanager.config.MinioConfig;
|
||||
import cn.crtech.cloud.resmanager.pojo.Resource;
|
||||
import cn.crtech.cloud.resmanager.server.Storage;
|
||||
import cn.hutool.core.util.ArrayUtil;
|
||||
import io.minio.MinioClient;
|
||||
import io.minio.ObjectStat;
|
||||
import io.minio.PutObjectOptions;
|
||||
import io.minio.errors.ErrorResponseException;
|
||||
import io.minio.http.Method;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@Component
|
||||
public class MinioStorage implements Storage {
|
||||
@Autowired
|
||||
private MinioConfig config;
|
||||
|
||||
@Override
|
||||
public String getType() {
|
||||
return "minio";
|
||||
}
|
||||
|
||||
private MinioClient minioClient;
|
||||
|
||||
@Override
|
||||
public void init() throws Exception {
|
||||
if (minioClient == null) {
|
||||
minioClient = new MinioClient(config.getEndpoint(), config.getPort(), config.getAccessKey(), config.getSecretKey(), config.getSecure());
|
||||
}
|
||||
if (!minioClient.bucketExists(config.getBucketName())) {
|
||||
minioClient.makeBucket(config.getBucketName());
|
||||
//设置桶权限
|
||||
// JSONObject jsonObject = new JSONObject();
|
||||
// ArrayList<Map<String,Object>> object = new ArrayList<Map<String, Object>>();
|
||||
// Map<String,Object> Map1 = new HashMap<>();
|
||||
// String[] str = new String[]{"s3:GetBucketLocation","s3:ListBucket"};
|
||||
// Map1.put("Action",str);
|
||||
// Map1.put("Effect","Allow");
|
||||
// Map1.put("Principal","*");
|
||||
// Map1.put("Resource","arn:aws:s3:::"+config.getBucketName());
|
||||
// object.add(Map1);
|
||||
// Map<String,Object> Map2 = new HashMap<>();
|
||||
// Map2.put("Action","s3:GetObject");
|
||||
// Map2.put("Effect","Allow");
|
||||
// Map2.put("Principal","*");
|
||||
// Map2.put("Resource","arn:aws:s3:::"+config.getBucketName()+"/myobject*");
|
||||
// object.add(Map2);
|
||||
// jsonObject.set("Statement",object);
|
||||
// jsonObject.set("Version","2012-10-17");
|
||||
// String policyJson = jsonObject.toString();
|
||||
// minioClient.setBucketPolicy(config.getBucketName(),policyJson);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUrl(Resource file, boolean download) throws Exception {
|
||||
String[] split = file.getPath().split("/");
|
||||
for (int i = 0; i < split.length; i++) {
|
||||
split[i] = URLEncoder.encode(split[i], "UTF-8");
|
||||
}
|
||||
String path = "/" + ArrayUtil.join(split, "/") + "/" + URLEncoder.encode(file.getName(), "UTF-8");
|
||||
if ("minio".equals(config.getAccessType())) {
|
||||
Map<String, String> queryParams = new HashMap<>();
|
||||
if (download) {
|
||||
queryParams.put("response-content-disposition", "attachment;");
|
||||
}
|
||||
return minioClient.getPresignedObjectUrl(Method.GET, config.getBucketName(), file.getPath().substring(1) + "/" + file.getName(), config.getUrlExpires(), queryParams);
|
||||
} else if (download) {
|
||||
return "/down/" + file.getMimeType() + path;
|
||||
} else {
|
||||
return "/res/" + file.getMimeType() + path;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream getStream(String relativePath) throws Exception {
|
||||
return minioClient.getObject(config.getBucketName(), relativePath.substring(1));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void store(Resource resource, MultipartFile file) throws Exception {
|
||||
try {
|
||||
ObjectStat objectStat = minioClient.statObject(config.getBucketName(), resource.getPath() + "/" + resource.getName());
|
||||
if (objectStat != null) {
|
||||
throw new Exception("文件已存在");
|
||||
}
|
||||
PutObjectOptions options = new PutObjectOptions(resource.getSize(), 5L * 1024 * 1024); //5M分片存储
|
||||
options.setContentType(resource.getMimeType());
|
||||
minioClient.putObject(config.getBucketName(), resource.getPath() + "/" + resource.getName(), file.getInputStream(), options);
|
||||
} catch (ErrorResponseException e) {
|
||||
if ("Object does not exist".equals(e.getMessage())) {
|
||||
PutObjectOptions options = new PutObjectOptions(resource.getSize(), 5L * 1024 * 1024); //5M分片存储
|
||||
options.setContentType(resource.getMimeType());
|
||||
minioClient.putObject(config.getBucketName(), resource.getPath() + "/" + resource.getName(), file.getInputStream(), options);
|
||||
} else {
|
||||
throw new Exception(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove(Resource file) throws Exception {
|
||||
minioClient.removeObject(config.getBucketName(), file.getPath() + "/" + file.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getExpireTime() {
|
||||
return config.getUrlExpires();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,48 @@
|
||||
package cn.crtech.cloud.resmanager.service;
|
||||
|
||||
import cn.crtech.cloud.common.dto.Result;
|
||||
import org.springframework.transaction.annotation.Propagation;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import tk.mybatis.mapper.common.Mapper;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Created by Onion on 2022/01/11.
|
||||
*/
|
||||
public abstract class BaseService<T> {
|
||||
public abstract Mapper<T> getMapper();
|
||||
|
||||
@Transactional(propagation = Propagation.REQUIRED)
|
||||
public Result add(T obj) {
|
||||
getMapper().insert(obj);
|
||||
return Result.success(obj, "操作成功!");
|
||||
}
|
||||
|
||||
@Transactional(propagation = Propagation.REQUIRED)
|
||||
public Result update(T obj) {
|
||||
getMapper().updateByPrimaryKeySelective(obj);
|
||||
return Result.success(obj, "操作成功!");
|
||||
}
|
||||
|
||||
@Transactional(propagation = Propagation.REQUIRED)
|
||||
public Result deleteById(int id) {
|
||||
getMapper().deleteByPrimaryKey(id);
|
||||
return Result.success(id, "操作成功!");
|
||||
}
|
||||
|
||||
@Transactional(propagation = Propagation.REQUIRED)
|
||||
public Result delete(T obj) {
|
||||
getMapper().delete(obj);
|
||||
return Result.success(obj, "操作成功!");
|
||||
}
|
||||
|
||||
public T getById(int id) {
|
||||
return (T) getMapper().selectByPrimaryKey(id);
|
||||
}
|
||||
|
||||
public abstract Result listByPage(Map<String, Object> params);
|
||||
|
||||
public abstract Result listByParams(Map<String, Object> params);
|
||||
|
||||
}
|
||||
@ -0,0 +1,203 @@
|
||||
package cn.crtech.cloud.resmanager.service;
|
||||
|
||||
import cn.crtech.cloud.common.dto.Result;
|
||||
import cn.crtech.cloud.common.utils.CommonFun;
|
||||
import cn.crtech.cloud.resmanager.mapper.ResourceMapper;
|
||||
import cn.crtech.cloud.resmanager.pojo.Resource;
|
||||
import cn.crtech.cloud.resmanager.server.ResmanagerServer;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.mock.web.MockMultipartFile;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import tk.mybatis.mapper.common.Mapper;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@Service("resService")
|
||||
public class ResourceService extends BaseService<Resource> {
|
||||
public static final String RESOURCE_URL_KEY = "RM:URL:";
|
||||
public static final String RESOURCE_DOWNLOAD_KEY = "RM:DOWNLOAD:";
|
||||
|
||||
@Autowired
|
||||
private ResourceMapper resourceMapper;
|
||||
|
||||
@Override
|
||||
public Mapper<Resource> getMapper() {
|
||||
return resourceMapper;
|
||||
}
|
||||
|
||||
@Autowired
|
||||
private RedisTemplate redisTemplate;
|
||||
|
||||
@Autowired
|
||||
private ResmanagerServer server;
|
||||
|
||||
public Resource get(String fileId) {
|
||||
return resourceMapper.selectByPrimaryKey(fileId);
|
||||
}
|
||||
|
||||
public List<Resource> listByIds(List<String> fileIds) {
|
||||
return resourceMapper.selectByIdList(fileIds);
|
||||
}
|
||||
|
||||
public int remove(List<String> fileIds) throws Exception {
|
||||
for (String fileId : fileIds) {
|
||||
Resource resource = get(fileId);
|
||||
if (resource.getIsTemp() == 1 && resource.getTempOper() == 1) {
|
||||
server.remove(resource);
|
||||
resourceMapper.deleteByPrimaryKey(fileId);
|
||||
} else {
|
||||
resource.setIsTemp(1);
|
||||
resource.setTempOper(3);
|
||||
resourceMapper.updateByPrimaryKeySelective(resource);
|
||||
}
|
||||
}
|
||||
return fileIds.size();
|
||||
}
|
||||
|
||||
public int commit(List<String> fileIds) throws Exception {
|
||||
for (String fileId : fileIds) {
|
||||
Resource resource = get(fileId);
|
||||
if (resource.getIsTemp() == 1 && resource.getTempOper() == 3) {
|
||||
server.remove(resource);
|
||||
resourceMapper.deleteByPrimaryKey(fileId);
|
||||
} else if (resource.getIsTemp() == 1) {
|
||||
resource.setIsTemp(0);
|
||||
resource.setTempOper(0);
|
||||
resource.setLastModifyTime(Calendar.getInstance().getTime());
|
||||
// resource.setLastModifyUser(loginUserHolder.getCurrentUser().getId());
|
||||
resourceMapper.updateByPrimaryKeySelective(resource);
|
||||
}
|
||||
}
|
||||
return fileIds.size();
|
||||
}
|
||||
|
||||
public int rollback(List<String> fileIds) throws Exception {
|
||||
for (String fileId : fileIds) {
|
||||
Resource resource = get(fileId);
|
||||
if (resource.getIsTemp() == 1 && resource.getTempOper() == 1) {
|
||||
server.remove(resource);
|
||||
resourceMapper.deleteByPrimaryKey(fileId);
|
||||
} else if (resource.getIsTemp() == 1) {
|
||||
resource.setIsTemp(0);
|
||||
resource.setTempOper(0);
|
||||
resourceMapper.updateByPrimaryKeySelective(resource);
|
||||
}
|
||||
}
|
||||
return fileIds.size();
|
||||
}
|
||||
|
||||
public String getUrl(String fileId, boolean download) throws Exception {
|
||||
String key = (download ? RESOURCE_DOWNLOAD_KEY : RESOURCE_URL_KEY) + fileId;
|
||||
String url = (String) redisTemplate.opsForValue().get(key);
|
||||
if (StrUtil.isNotBlank(url)) {
|
||||
return url;
|
||||
}
|
||||
Resource resource = get(fileId);
|
||||
url = server.getUrl(resource, download);
|
||||
redisTemplate.opsForValue().set(key, url, server.getExpireTime(), TimeUnit.SECONDS);
|
||||
return url;
|
||||
}
|
||||
|
||||
public List<String> getMuchUrl(List<String> list, boolean download) throws Exception {
|
||||
List<String> backList = new ArrayList<>();
|
||||
for (int i = 0; i <= (list.size() - 1); i++) {
|
||||
String url = getUrl(list.get(i), download);
|
||||
backList.add(url);
|
||||
}
|
||||
return backList;
|
||||
}
|
||||
|
||||
public InputStream getStream(String fileId) throws Exception {
|
||||
Resource resource = get(fileId);
|
||||
return server.getStream(resource.getPath());
|
||||
}
|
||||
|
||||
public InputStream getStreamByFileId(String fileId) throws Exception {
|
||||
return server.getStreamByResource(get(fileId));
|
||||
}
|
||||
|
||||
public InputStream getStreamByPath(String relativePath) throws Exception {
|
||||
return server.getStream(relativePath);
|
||||
}
|
||||
|
||||
public Resource addFile(@NotNull MultipartFile file, String path, String name, String description) throws Exception {
|
||||
/* UserDto userDto = loginUserHolder.getCurrentUser();*/
|
||||
Resource resource = new Resource();
|
||||
resource.setId(CommonFun.getSSID() + "");
|
||||
resource.setMimeType(file.getContentType());
|
||||
resource.setName(StrUtil.isBlank(name) ? file.getOriginalFilename() : name);
|
||||
resource.setSize(file.getSize());
|
||||
resource.setPath(StrUtil.isBlank(path) ? "/" : (path.startsWith("/") ? path : ("/" + path)));
|
||||
resource.setDescription(description);
|
||||
resource.setCreateTime(Calendar.getInstance().getTime());
|
||||
/* if (userDto != null) {
|
||||
resource.setCreateUser(loginUserHolder.getCurrentUser().getId());
|
||||
resource.setLastModifyUser(loginUserHolder.getCurrentUser().getId());
|
||||
}*/
|
||||
resource.setLastModifyTime(Calendar.getInstance().getTime());
|
||||
|
||||
resource.setIsTemp(1);
|
||||
resource.setTempOper(1);
|
||||
|
||||
synchronized (this) {
|
||||
server.store(resource, file);
|
||||
}
|
||||
|
||||
resourceMapper.insert(resource);
|
||||
return resource;
|
||||
}
|
||||
|
||||
public Resource copyOfMinIoFile(String fileId) throws Exception {
|
||||
Resource selectResource = get(fileId);
|
||||
if (selectResource == null) {
|
||||
return null;
|
||||
}
|
||||
MultipartFile multipartFile = new MockMultipartFile(selectResource.getName(), getStreamByFileId(fileId));
|
||||
String fileName = selectResource.getName();
|
||||
//创建新文件
|
||||
Resource resource = new Resource();
|
||||
resource.setId(CommonFun.getSSID() + "");
|
||||
resource.setMimeType(selectResource.getMimeType());
|
||||
resource.setName(CommonFun.getSSID() + "." + getFileSuffixName(selectResource.getName()));
|
||||
resource.setSize(multipartFile.getSize());
|
||||
resource.setPath(selectResource.getPath());
|
||||
resource.setDescription("复制文件");
|
||||
resource.setCreateTime(Calendar.getInstance().getTime());
|
||||
resource.setLastModifyTime(Calendar.getInstance().getTime());
|
||||
resource.setIsTemp(1);
|
||||
resource.setTempOper(1);
|
||||
synchronized (this) {
|
||||
server.store(resource, multipartFile);
|
||||
}
|
||||
|
||||
resourceMapper.insert(resource);
|
||||
return resource;
|
||||
}
|
||||
|
||||
public static String getFileSuffixName(String image_name) {
|
||||
return image_name.contains(".") ? image_name.substring(image_name.lastIndexOf(".") + 1) : null;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Result listByPage(Map<String, Object> params) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result listByParams(Map<String, Object> params) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
49
ResourceManager/src/main/resources/application-dev.yml
Normal file
49
ResourceManager/src/main/resources/application-dev.yml
Normal file
@ -0,0 +1,49 @@
|
||||
server:
|
||||
port: 8082
|
||||
servlet:
|
||||
encoding:
|
||||
charset: utf-8
|
||||
enabled: true
|
||||
force: true
|
||||
tomcat:
|
||||
uri-encoding: UTF-8
|
||||
logging:
|
||||
config: classpath:logback.xml
|
||||
file:
|
||||
path: logs/crtech-cloud-resmanager.log
|
||||
level:
|
||||
cn.crtech.cloud.resmanager: debug
|
||||
spring:
|
||||
servlet:
|
||||
multipart:
|
||||
enabled: true
|
||||
max-file-size: 100MB
|
||||
max-request-size: 1024MB
|
||||
mybatis:
|
||||
mapper-locations: classpath:/mapping/*.xml
|
||||
type-aliases-package: cn.crtech.cloud.resmanager.pojo
|
||||
#配置驼峰下划线
|
||||
configuration:
|
||||
map-underscore-to-camel-case: true
|
||||
resmanager:
|
||||
type: minio #local,minio,aliyunoss
|
||||
local:
|
||||
path: D:/minioserver
|
||||
bucket-name: crtech-cloud
|
||||
minio:
|
||||
endpoint: 127.0.0.1
|
||||
port: 9000
|
||||
access-key: minioadmin
|
||||
secret-key: minioadmin
|
||||
bucket-name: crtech-cloud
|
||||
secure: false
|
||||
access-type: minio #minio 直接获取minio的url-expires秒的有效url,local 获取本服务转发地址
|
||||
url-expires: 1800 #minio直连url有效时间:1~604800 秒
|
||||
aliyunoss:
|
||||
server-url: https://
|
||||
access-key: minioadmin
|
||||
secret-key: minioadmin
|
||||
bucket-name: crtech-cloud
|
||||
secure: false
|
||||
access-type: aliyunoss #aliyunoss 直接获取minio的url-expires秒的有效url,local 获取本服务转发地址
|
||||
url-expires: 1800 #minio直连url有效时间:1~604800 秒
|
||||
49
ResourceManager/src/main/resources/application-prod.yml
Normal file
49
ResourceManager/src/main/resources/application-prod.yml
Normal file
@ -0,0 +1,49 @@
|
||||
server:
|
||||
port: 8082
|
||||
servlet:
|
||||
encoding:
|
||||
charset: utf-8
|
||||
enabled: true
|
||||
force: true
|
||||
tomcat:
|
||||
uri-encoding: UTF-8
|
||||
logging:
|
||||
config: classpath:logback.xml
|
||||
file:
|
||||
path: logs/crtech-cloud-resmanager.log
|
||||
level:
|
||||
cn.crtech.cloud.resmanager: debug
|
||||
spring:
|
||||
servlet:
|
||||
multipart:
|
||||
enabled: true
|
||||
max-file-size: 100MB
|
||||
max-request-size: 1024MB
|
||||
mybatis:
|
||||
mapper-locations: classpath:/mapping/*.xml
|
||||
type-aliases-package: cn.crtech.cloud.resmanager.pojo
|
||||
#配置驼峰下划线
|
||||
configuration:
|
||||
map-underscore-to-camel-case: true
|
||||
resmanager:
|
||||
type: minio #local,minio,aliyunoss
|
||||
local:
|
||||
path: D:/minioserver
|
||||
bucket-name: crtech-cloud
|
||||
minio:
|
||||
endpoint: http://api.yaoxunk.com
|
||||
port: 9008
|
||||
access-key: minioadmin
|
||||
secret-key: minioadmin
|
||||
bucket-name: crtech-cloud
|
||||
secure: false
|
||||
access-type: minio #minio 直接获取minio的url-expires秒的有效url,local 获取本服务转发地址
|
||||
url-expires: 1800 #minio直连url有效时间:1~604800 秒
|
||||
aliyunoss:
|
||||
server-url: https://
|
||||
access-key: minioadmin
|
||||
secret-key: minioadmin
|
||||
bucket-name: crtech-cloud
|
||||
secure: false
|
||||
access-type: aliyunoss #aliyunoss 直接获取minio的url-expires秒的有效url,local 获取本服务转发地址
|
||||
url-expires: 1800 #minio直连url有效时间:1~604800 秒
|
||||
16
ResourceManager/src/main/resources/bootstrap-dev.yml
Normal file
16
ResourceManager/src/main/resources/bootstrap-dev.yml
Normal file
@ -0,0 +1,16 @@
|
||||
spring:
|
||||
application:
|
||||
name: crtech-cloud-resmanager # 项目名称尽量用小写
|
||||
cloud:
|
||||
nacos:
|
||||
discovery:
|
||||
server-addr: localhost:8848
|
||||
redis:
|
||||
database: 0
|
||||
port: 6379
|
||||
host: localhost
|
||||
password:
|
||||
datasource:
|
||||
url: jdbc:mysql://chaoran.crtech.cn:9803/cr_cloud_general_dev?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&useSSL=false&allowPublicKeyRetrieval=true
|
||||
username: crtech
|
||||
password: www.server41.com
|
||||
16
ResourceManager/src/main/resources/bootstrap-prod.yml
Normal file
16
ResourceManager/src/main/resources/bootstrap-prod.yml
Normal file
@ -0,0 +1,16 @@
|
||||
spring:
|
||||
application:
|
||||
name: crtech-cloud-resmanager # 项目名称尽量用小写
|
||||
cloud:
|
||||
nacos:
|
||||
discovery:
|
||||
server-addr: http://api.yaoxunk.com:28848
|
||||
redis:
|
||||
database: 0
|
||||
port: 6689
|
||||
host: 127.0.0.1
|
||||
password:
|
||||
datasource:
|
||||
url: jdbc:mysql://rm-uf6wn1g5bm13lf3363o.mysql.rds.aliyuncs.com:3306/cr_cloud_general?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&useSSL=false&allowPublicKeyRetrieval=true
|
||||
username: crtech
|
||||
password: Crtech@yun_2023
|
||||
6
ResourceManager/src/main/resources/bootstrap.yml
Normal file
6
ResourceManager/src/main/resources/bootstrap.yml
Normal file
@ -0,0 +1,6 @@
|
||||
spring:
|
||||
profiles:
|
||||
active: dev
|
||||
|
||||
|
||||
|
||||
56
ResourceManager/src/main/resources/logback.xml
Normal file
56
ResourceManager/src/main/resources/logback.xml
Normal file
@ -0,0 +1,56 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration>
|
||||
<appender name="FILE"
|
||||
class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
||||
<fileNamePattern>logs/crtech-cloud-resmanager.%d{yyyy-MM-dd}.log
|
||||
</fileNamePattern>
|
||||
</rollingPolicy>
|
||||
|
||||
<encoder>
|
||||
<pattern>%d{yyyy-MM-dd_HH:mm:ss} %logger{18} -%msg%n
|
||||
</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||
|
||||
<encoder>
|
||||
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
|
||||
</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<appender name="ASYNC" class="ch.qos.logback.classic.AsyncAppender">
|
||||
<discardingThreshold>0</discardingThreshold>
|
||||
<queueSize>1000</queueSize>
|
||||
<appender-ref ref="FILE" />
|
||||
</appender>
|
||||
|
||||
<logger name="org" level="info" additivity="false">
|
||||
<appender-ref ref="FILE"></appender-ref>
|
||||
<appender-ref ref="STDOUT"></appender-ref>
|
||||
</logger>
|
||||
<logger name="com" level="info" additivity="false">
|
||||
<appender-ref ref="FILE"></appender-ref>
|
||||
<appender-ref ref="STDOUT"></appender-ref>
|
||||
</logger>
|
||||
<logger name="net" level="info" additivity="false">
|
||||
<appender-ref ref="FILE"></appender-ref>
|
||||
<appender-ref ref="STDOUT"></appender-ref>
|
||||
</logger>
|
||||
|
||||
<logger name="com.netflix" level="debug" additivity="false">
|
||||
<appender-ref ref="STDOUT"></appender-ref>
|
||||
<appender-ref ref="FILE"></appender-ref>
|
||||
</logger>
|
||||
|
||||
<logger name="cn.crtech.cloud.resmanager" level="debug" additivity="false">
|
||||
<appender-ref ref="STDOUT"></appender-ref>
|
||||
<appender-ref ref="FILE"></appender-ref>
|
||||
</logger>
|
||||
<root level="INFO">
|
||||
<appender-ref ref="ASYNC" />
|
||||
</root>
|
||||
</configuration>
|
||||
29
ResourceManager/src/main/resources/public/sdk.js
Normal file
29
ResourceManager/src/main/resources/public/sdk.js
Normal file
File diff suppressed because one or more lines are too long
37
ResourceManager/src/main/resources/public/test.html
Normal file
37
ResourceManager/src/main/resources/public/test.html
Normal file
@ -0,0 +1,37 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Title</title>
|
||||
<script type="application/javascript" src="sdk.js"></script>
|
||||
<style>
|
||||
.preview {
|
||||
width: 100%;
|
||||
height: 50vh;
|
||||
background-color: rgba(0,0,0,0.75);
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
background-size: 80%;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<fieldset>
|
||||
<legend>上传文件</legend>
|
||||
<label>文件路径:<input name="path" value="ERP/商品图片/SP000001"></label>
|
||||
<label>重命名文件:<input name="name" value="2.png"></label>
|
||||
<label>文件:<input type="file" name="file" accept="image/png,image/jpeg"></label>
|
||||
</fieldset>
|
||||
<fieldset>
|
||||
<legend>图片预览</legend>
|
||||
<div class="preview"></div>
|
||||
</fieldset>
|
||||
</body>
|
||||
<script type="application/javascript">
|
||||
window.onload = () => {
|
||||
console.log($rm.server_url);
|
||||
let preview = document.getElementsByClassName("preview");
|
||||
preview[0].setAttribute("style", "background-image: url('" + $rm.server_url + "/s/123')")
|
||||
};
|
||||
</script>
|
||||
</html>
|
||||
Reference in New Issue
Block a user