Commit 0c13553fbb7fd45051aabd403c2e513a6edfa62b
1 parent
94f0dec9
fix: 在MinioService注入的时候,默认不创建存储桶。在上传文件时按日期(yyyy-MM-dd)格式来存储文件
Showing
3 changed files
with
60 additions
and
42 deletions
@@ -1188,7 +1188,7 @@ file: | @@ -1188,7 +1188,7 @@ file: | ||
1188 | randomFileName: true #是否重命名文件名字,防止冲突 | 1188 | randomFileName: true #是否重命名文件名字,防止冲突 |
1189 | local: | 1189 | local: |
1190 | uploadDir: /Users/thingskit/upload/ #文件上传地址 只有type = local需要 | 1190 | uploadDir: /Users/thingskit/upload/ #文件上传地址 只有type = local需要 |
1191 | - downloadPath: /downloadFile/ #与controller里面下载文件GetMapping的path一致, 只有type = local需要 | 1191 | + downloadPath: /download_file/ #与controller里面下载文件GetMapping的path一致, 只有type = local需要 |
1192 | uploadPath: /upload #与controller里面下载文件GetMapping的path一致, 只有type = local需要 | 1192 | uploadPath: /upload #与controller里面下载文件GetMapping的path一致, 只有type = local需要 |
1193 | staticUrl: /oss/files/** #oss静态访问路径 只有type = local需要 | 1193 | staticUrl: /oss/files/** #oss静态访问路径 只有type = local需要 |
1194 | randomFileName: ${file.storage.randomFileName} | 1194 | randomFileName: ${file.storage.randomFileName} |
@@ -87,6 +87,8 @@ public enum ErrorMessage { | @@ -87,6 +87,8 @@ public enum ErrorMessage { | ||
87 | DUPLICATE_IDENTIFIERS_EXIST(400063,"存在重复的功能标识符。"), | 87 | DUPLICATE_IDENTIFIERS_EXIST(400063,"存在重复的功能标识符。"), |
88 | SMS_CONFIG_ERROR(400064,"短信配置错误。"), | 88 | SMS_CONFIG_ERROR(400064,"短信配置错误。"), |
89 | INVALID_TOPIC(400065,"无效Topic。"), | 89 | INVALID_TOPIC(400065,"无效Topic。"), |
90 | + BUCKET_NOT_CONFORM_RENAME_RULE(400066,"存储桶不符合命名规范!!"), | ||
91 | + MINIO_KEY_AND_SIGNATURE_ERROR(400067,"Minio签名不匹配!!"), | ||
90 | HAVE_NO_PERMISSION(500002,"没有修改权限"); | 92 | HAVE_NO_PERMISSION(500002,"没有修改权限"); |
91 | private final int code; | 93 | private final int code; |
92 | private String message; | 94 | private String message; |
@@ -17,12 +17,14 @@ import org.springframework.web.context.request.RequestContextHolder; | @@ -17,12 +17,14 @@ import org.springframework.web.context.request.RequestContextHolder; | ||
17 | import org.springframework.web.context.request.ServletRequestAttributes; | 17 | import org.springframework.web.context.request.ServletRequestAttributes; |
18 | import org.springframework.web.multipart.MultipartFile; | 18 | import org.springframework.web.multipart.MultipartFile; |
19 | import org.thingsboard.server.common.data.yunteng.core.exception.FileStorageException; | 19 | import org.thingsboard.server.common.data.yunteng.core.exception.FileStorageException; |
20 | +import org.thingsboard.server.common.data.yunteng.core.exception.TkDataValidationException; | ||
20 | import org.thingsboard.server.common.data.yunteng.core.message.ErrorMessage; | 21 | import org.thingsboard.server.common.data.yunteng.core.message.ErrorMessage; |
21 | import org.thingsboard.server.common.data.yunteng.dto.FileUploadResponse; | 22 | import org.thingsboard.server.common.data.yunteng.dto.FileUploadResponse; |
22 | 23 | ||
23 | import javax.net.ssl.*; | 24 | import javax.net.ssl.*; |
24 | import javax.servlet.http.HttpServletRequest; | 25 | import javax.servlet.http.HttpServletRequest; |
25 | import javax.servlet.http.HttpServletResponse; | 26 | import javax.servlet.http.HttpServletResponse; |
27 | +import java.io.File; | ||
26 | import java.io.IOException; | 28 | import java.io.IOException; |
27 | import java.io.InputStream; | 29 | import java.io.InputStream; |
28 | import java.io.OutputStream; | 30 | import java.io.OutputStream; |
@@ -31,6 +33,8 @@ import java.security.KeyManagementException; | @@ -31,6 +33,8 @@ import java.security.KeyManagementException; | ||
31 | import java.security.NoSuchAlgorithmException; | 33 | import java.security.NoSuchAlgorithmException; |
32 | import java.security.SecureRandom; | 34 | import java.security.SecureRandom; |
33 | import java.security.cert.X509Certificate; | 35 | import java.security.cert.X509Certificate; |
36 | +import java.time.LocalDateTime; | ||
37 | +import java.time.format.DateTimeFormatter; | ||
34 | import java.util.Objects; | 38 | import java.util.Objects; |
35 | 39 | ||
36 | @Service | 40 | @Service |
@@ -50,10 +54,8 @@ public class MinioFileStorageService implements FileStorageService { | @@ -50,10 +54,8 @@ public class MinioFileStorageService implements FileStorageService { | ||
50 | MinioClient.builder() | 54 | MinioClient.builder() |
51 | .endpoint(fileStorageProperties.getMinioUrl()) | 55 | .endpoint(fileStorageProperties.getMinioUrl()) |
52 | .credentials(fileStorageProperties.getMinioName(), fileStorageProperties.getMinioPass()) | 56 | .credentials(fileStorageProperties.getMinioName(), fileStorageProperties.getMinioPass()) |
53 | - .httpClient(getUnsafeOkHttpClient()) | 57 | + .httpClient(Objects.requireNonNull(getUnsafeOkHttpClient())) |
54 | .build(); | 58 | .build(); |
55 | - // 创建储存桶 | ||
56 | - checkBucket(); | ||
57 | } | 59 | } |
58 | 60 | ||
59 | public static OkHttpClient getUnsafeOkHttpClient() throws KeyManagementException { | 61 | public static OkHttpClient getUnsafeOkHttpClient() throws KeyManagementException { |
@@ -94,12 +96,22 @@ public class MinioFileStorageService implements FileStorageService { | @@ -94,12 +96,22 @@ public class MinioFileStorageService implements FileStorageService { | ||
94 | // Normalize file name | 96 | // Normalize file name |
95 | String fileName = StringUtils.cleanPath(Objects.requireNonNull(file.getOriginalFilename())); | 97 | String fileName = StringUtils.cleanPath(Objects.requireNonNull(file.getOriginalFilename())); |
96 | // random fileName if needed | 98 | // random fileName if needed |
99 | + | ||
97 | // 储存 | 100 | // 储存 |
98 | try { | 101 | try { |
99 | return storeFileByInputStream(fileName, file.getContentType(), file.getInputStream()); | 102 | return storeFileByInputStream(fileName, file.getContentType(), file.getInputStream()); |
100 | - } catch (Exception ex) { | ||
101 | - ex.printStackTrace(); | 103 | + } catch (IOException ex) { |
102 | throw new FileStorageException(ErrorMessage.STORE_FILE_FAILED); | 104 | throw new FileStorageException(ErrorMessage.STORE_FILE_FAILED); |
105 | + } catch (TkDataValidationException | ||
106 | + | ServerException | ||
107 | + | InsufficientDataException | ||
108 | + | ErrorResponseException | ||
109 | + | NoSuchAlgorithmException | ||
110 | + | InvalidKeyException | ||
111 | + | InvalidResponseException | ||
112 | + | XmlParserException | ||
113 | + | InternalException e) { | ||
114 | + throw new TkDataValidationException(e.getMessage()); | ||
103 | } | 115 | } |
104 | } | 116 | } |
105 | 117 | ||
@@ -107,18 +119,14 @@ public class MinioFileStorageService implements FileStorageService { | @@ -107,18 +119,14 @@ public class MinioFileStorageService implements FileStorageService { | ||
107 | public FileUploadResponse upload(MultipartFile file) { | 119 | public FileUploadResponse upload(MultipartFile file) { |
108 | String fileName = this.storeFile(file); | 120 | String fileName = this.storeFile(file); |
109 | String staticPath = getPath(fileName); | 121 | String staticPath = getPath(fileName); |
110 | - String realDownloadPath = null; | ||
111 | - try { | ||
112 | - // 获取request | ||
113 | - HttpServletRequest request = | ||
114 | - ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); | ||
115 | - // 生成下载接口的地址 | ||
116 | - realDownloadPath = | ||
117 | - request.getRequestURL().toString().replace("upload", "downloadFile/" + fileName); | ||
118 | - } catch (Exception e) { | ||
119 | - e.printStackTrace(); | ||
120 | - log.info("Could not upload file " + fileName + ". Please try again!"); | ||
121 | - } | 122 | + // 获取request |
123 | + HttpServletRequest request = | ||
124 | + ((ServletRequestAttributes) | ||
125 | + Objects.requireNonNull(RequestContextHolder.getRequestAttributes())) | ||
126 | + .getRequest(); | ||
127 | + // 生成下载接口的地址 | ||
128 | + String realDownloadPath = | ||
129 | + request.getRequestURL().toString().replace("upload", "downloadFile/" + fileName); | ||
122 | return new FileUploadResponse( | 130 | return new FileUploadResponse( |
123 | fileName, realDownloadPath, file.getContentType(), file.getSize(), staticPath); | 131 | fileName, realDownloadPath, file.getContentType(), file.getSize(), staticPath); |
124 | } | 132 | } |
@@ -165,29 +173,29 @@ public class MinioFileStorageService implements FileStorageService { | @@ -165,29 +173,29 @@ public class MinioFileStorageService implements FileStorageService { | ||
165 | } | 173 | } |
166 | } | 174 | } |
167 | 175 | ||
168 | - // 检查储存桶情况 | ||
169 | - private void checkBucket() { | ||
170 | - try { | ||
171 | - // 桶是否存在 | ||
172 | - boolean exists = | ||
173 | - minioClient.bucketExists( | ||
174 | - BucketExistsArgs.builder().bucket(fileStorageProperties.getBucketName()).build()); | ||
175 | - if (!exists) { | ||
176 | - // 不存在创建 | ||
177 | - minioClient.makeBucket( | ||
178 | - MakeBucketArgs.builder().bucket(fileStorageProperties.getBucketName()).build()); | ||
179 | - // 设置储存桶策略 | ||
180 | - String str = | ||
181 | - "{\"Statement\": [{\"Action\": [\"s3:GetBucketLocation\",\"s3:ListBucket\"],\"Effect\": \"Allow\",\"Principal\": \"*\",\"Resource\": \"arn:aws:s3:::%\"},{\"Action\": \"s3:GetObject\",\"Effect\": \"Allow\",\"Principal\": \"*\",\"Resource\": \"arn:aws:s3:::%/*\"}],\"Version\": \"2012-10-17\"}"; | ||
182 | - String replace = str.replace("%", fileStorageProperties.getBucketName()); | ||
183 | - minioClient.setBucketPolicy( | ||
184 | - SetBucketPolicyArgs.builder() | ||
185 | - .bucket(fileStorageProperties.getBucketName()) | ||
186 | - .config(replace) | ||
187 | - .build()); | ||
188 | - } | ||
189 | - } catch (Exception e) { | ||
190 | - log.error(e.getMessage(), e); | 176 | + private void checkBucket() |
177 | + throws ServerException, InsufficientDataException, ErrorResponseException, IOException, | ||
178 | + NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, | ||
179 | + XmlParserException, InternalException { | ||
180 | + String bucketName = fileStorageProperties.getBucketName(); | ||
181 | + // 桶是否存在 | ||
182 | + boolean exists = | ||
183 | + minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build()); | ||
184 | + if (!exists) { | ||
185 | + // 不存在创建 | ||
186 | + minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build()); | ||
187 | + // 设置储存桶策略 | ||
188 | + String str = | ||
189 | + "{\"Statement\": [{\"Action\": [\"s3:GetBucketLocation\",\"s3:ListBucket\"]," | ||
190 | + + "\"Effect\": \"Allow\",\"Principal\": \"*\",\"Resource\": \"arn:aws:s3:::%\"},{\"Action\": " | ||
191 | + + "\"s3:GetObject\",\"Effect\": \"Allow\",\"Principal\": \"*\"," | ||
192 | + + "\"Resource\": \"arn:aws:s3:::%/*\"}],\"Version\": \"2012-10-17\"}"; | ||
193 | + String replace = str.replace("%", fileStorageProperties.getBucketName()); | ||
194 | + minioClient.setBucketPolicy( | ||
195 | + SetBucketPolicyArgs.builder() | ||
196 | + .bucket(fileStorageProperties.getBucketName()) | ||
197 | + .config(replace) | ||
198 | + .build()); | ||
191 | } | 199 | } |
192 | } | 200 | } |
193 | 201 | ||
@@ -222,7 +230,15 @@ public class MinioFileStorageService implements FileStorageService { | @@ -222,7 +230,15 @@ public class MinioFileStorageService implements FileStorageService { | ||
222 | if (fileName.contains("..")) { | 230 | if (fileName.contains("..")) { |
223 | throw new FileStorageException(ErrorMessage.STORE_FILE_FAILED); | 231 | throw new FileStorageException(ErrorMessage.STORE_FILE_FAILED); |
224 | } | 232 | } |
225 | - checkBucket(); | 233 | + try { |
234 | + checkBucket(); | ||
235 | + } catch (ErrorResponseException e) { | ||
236 | + throw new TkDataValidationException(ErrorMessage.MINIO_KEY_AND_SIGNATURE_ERROR.getMessage()); | ||
237 | + } catch (Exception e) { | ||
238 | + throw new TkDataValidationException(ErrorMessage.BUCKET_NOT_CONFORM_RENAME_RULE.getMessage()); | ||
239 | + } | ||
240 | + String date = LocalDateTime.now().format(DateTimeFormatter.ISO_DATE); | ||
241 | + fileName = date + "/" + fileName; | ||
226 | PutObjectArgs build = | 242 | PutObjectArgs build = |
227 | PutObjectArgs.builder() | 243 | PutObjectArgs.builder() |
228 | .bucket(fileStorageProperties.getBucketName()) | 244 | .bucket(fileStorageProperties.getBucketName()) |