|
@@ -1,122 +1,138 @@
|
|
package com.qmth.boot.core.fss.store.impl;
|
|
package com.qmth.boot.core.fss.store.impl;
|
|
|
|
|
|
-import com.aliyun.oss.ClientBuilderConfiguration;
|
|
|
|
-import com.aliyun.oss.OSS;
|
|
|
|
-import com.aliyun.oss.OSSClientBuilder;
|
|
|
|
-import com.aliyun.oss.model.OSSObject;
|
|
|
|
-import com.aliyun.oss.model.ObjectMetadata;
|
|
|
|
|
|
+import com.qmth.boot.core.fss.exception.OssApiException;
|
|
import com.qmth.boot.core.fss.store.FileStore;
|
|
import com.qmth.boot.core.fss.store.FileStore;
|
|
-import org.apache.commons.lang3.StringUtils;
|
|
|
|
-import org.springframework.util.Assert;
|
|
|
|
-
|
|
|
|
|
|
+import com.qmth.boot.core.fss.utils.OssApiParam;
|
|
|
|
+import com.qmth.boot.core.fss.utils.OssConfig;
|
|
|
|
+import com.qmth.boot.core.fss.utils.OssSigner;
|
|
|
|
+import com.qmth.boot.tools.models.ByteArray;
|
|
|
|
+import okhttp3.*;
|
|
|
|
+
|
|
|
|
+import javax.activation.MimetypesFileTypeMap;
|
|
|
|
+import java.io.IOException;
|
|
import java.io.InputStream;
|
|
import java.io.InputStream;
|
|
|
|
+import java.nio.charset.StandardCharsets;
|
|
import java.time.Duration;
|
|
import java.time.Duration;
|
|
-import java.util.Date;
|
|
|
|
-import java.util.regex.Matcher;
|
|
|
|
-import java.util.regex.Pattern;
|
|
|
|
|
|
|
|
-/**
|
|
|
|
- * OSS文件管理工具
|
|
|
|
- */
|
|
|
|
public class OssStore implements FileStore {
|
|
public class OssStore implements FileStore {
|
|
|
|
|
|
- private static final String ENDPOINT_PREFIX_HTTPS = "https://";
|
|
|
|
-
|
|
|
|
- private static final String ENDPOINT_PREFIX_HTTP = "http://";
|
|
|
|
-
|
|
|
|
- private static final Pattern CONFIG_PATTERN = Pattern.compile("^oss://([\\w]+):([\\w]+)@([\\w-]+).([\\w-.]+)$");
|
|
|
|
-
|
|
|
|
- private String server;
|
|
|
|
-
|
|
|
|
- private String bucket;
|
|
|
|
-
|
|
|
|
- private OSS ossClient;
|
|
|
|
-
|
|
|
|
- private OSS temporaryUrlClient;
|
|
|
|
|
|
+ private OkHttpClient client;
|
|
|
|
|
|
- public OssStore(String server, String config) {
|
|
|
|
- String message = "fss.config: " + config + ": pattern error";
|
|
|
|
- Matcher m = CONFIG_PATTERN.matcher(config);
|
|
|
|
- if (m.find()) {
|
|
|
|
- String accessKey = StringUtils.trimToNull(m.group(1));
|
|
|
|
- String accessSecret = StringUtils.trimToNull(m.group(2));
|
|
|
|
- this.bucket = StringUtils.trimToNull(m.group(3));
|
|
|
|
- String endpoint = StringUtils.trimToNull(m.group(4));
|
|
|
|
|
|
+ private OssConfig config;
|
|
|
|
|
|
- Assert.notNull(accessKey, message);
|
|
|
|
- Assert.notNull(accessSecret, message);
|
|
|
|
- Assert.notNull(bucket, message);
|
|
|
|
- Assert.notNull(endpoint, message);
|
|
|
|
|
|
+ private MimetypesFileTypeMap mimeTypes;
|
|
|
|
|
|
- this.server = server;
|
|
|
|
- //判断是否阿里云OSS地址还是私服,使用不同的前缀
|
|
|
|
- if (endpoint.contains("aliyun")) {
|
|
|
|
- endpoint = ENDPOINT_PREFIX_HTTPS.concat(endpoint);
|
|
|
|
- } else {
|
|
|
|
- endpoint = ENDPOINT_PREFIX_HTTP.concat(endpoint);
|
|
|
|
- }
|
|
|
|
- this.ossClient = new OSSClientBuilder().build(endpoint, accessKey, accessSecret);
|
|
|
|
- //为支持私有读的bucket,构造专门用于获取临时访问URL的client
|
|
|
|
- ClientBuilderConfiguration conf = new ClientBuilderConfiguration();
|
|
|
|
- conf.setSupportCname(true);
|
|
|
|
- this.temporaryUrlClient = new OSSClientBuilder().build(server, accessKey, accessSecret, conf);
|
|
|
|
- } else {
|
|
|
|
- throw new IllegalArgumentException(message);
|
|
|
|
- }
|
|
|
|
|
|
+ public OssStore(OssConfig config) {
|
|
|
|
+ this.client = new OkHttpClient.Builder().connectionPool(new ConnectionPool())
|
|
|
|
+ .connectTimeout(Duration.ofSeconds(10)).readTimeout(Duration.ofSeconds(30)).build();
|
|
|
|
+ this.config = config;
|
|
|
|
+ this.mimeTypes = new MimetypesFileTypeMap();
|
|
}
|
|
}
|
|
|
|
|
|
- @Override
|
|
|
|
- public String getServer() {
|
|
|
|
- return server;
|
|
|
|
|
|
+ private Headers buildHeader(OssApiParam header, String authorization) {
|
|
|
|
+ Headers.Builder builder = new Headers.Builder();
|
|
|
|
+ builder.add("Date", OssSigner.getGmtDateTime(header.getDate()));
|
|
|
|
+ builder.add("x-oss-date", OssSigner.getIso8601DateTime(header.getDate()));
|
|
|
|
+ builder.add("x-oss-content-sha256", "UNSIGNED-PAYLOAD");
|
|
|
|
+ if (header.getCopySource() != null) {
|
|
|
|
+ builder.add("x-oss-copy-source", header.getCopySource());
|
|
|
|
+ }
|
|
|
|
+ if (header.getContentMd5() != null) {
|
|
|
|
+ builder.add("content-md5", header.getContentMd5());
|
|
|
|
+ }
|
|
|
|
+ if (header.getContentType() != null) {
|
|
|
|
+ builder.add("content-type", header.getContentType());
|
|
|
|
+ }
|
|
|
|
+ builder.add("Authorization", authorization);
|
|
|
|
+ return builder.build();
|
|
}
|
|
}
|
|
|
|
|
|
@Override
|
|
@Override
|
|
- public String getPresignedUrl(String path, Duration expireDuration) {
|
|
|
|
- return temporaryUrlClient.generatePresignedUrl(bucket, formatPath(path),
|
|
|
|
- new Date(System.currentTimeMillis() + expireDuration.toMillis())).toString();
|
|
|
|
|
|
+ public void copy(String source, String target) throws Exception {
|
|
|
|
+ source = formatPath(source);
|
|
|
|
+ target = formatPath(target);
|
|
|
|
+ OssApiParam header = new OssApiParam().setCopySource("/" + config.getBucket() + "/" + source);
|
|
|
|
+ Request request = new Request.Builder().url(config.getEndpoint() + "/" + target)
|
|
|
|
+ .headers(buildHeader(header, OssSigner.buildHeader(config, "put", target, header)))
|
|
|
|
+ .put(RequestBody.create(null, new byte[0])).build();
|
|
|
|
+ Response response = client.newCall(request).execute();
|
|
|
|
+ if (!response.isSuccessful()) {
|
|
|
|
+ String error = response.body() != null ? new String(response.body().bytes(), StandardCharsets.UTF_8) : "";
|
|
|
|
+ throw new OssApiException(response.code(), error);
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
@Override
|
|
@Override
|
|
- public void write(String path, InputStream ins, String md5) {
|
|
|
|
- ObjectMetadata metadata = new ObjectMetadata();
|
|
|
|
- metadata.setContentMD5(toBase64(md5));
|
|
|
|
- ossClient.putObject(bucket, formatPath(path), ins, metadata);
|
|
|
|
|
|
+ public void write(String path, InputStream ins, String md5) throws Exception {
|
|
|
|
+ path = formatPath(path);
|
|
|
|
+ OssApiParam param = new OssApiParam().setContentMd5(toBase64(md5))
|
|
|
|
+ .setContentType(mimeTypes.getContentType(path));
|
|
|
|
+ RequestBody body = RequestBody
|
|
|
|
+ .create(MediaType.parse(param.getContentType()), ByteArray.fromInputStream(ins).value());
|
|
|
|
+ Request request = new Request.Builder().url(config.getEndpoint() + "/" + path)
|
|
|
|
+ .headers(buildHeader(param, OssSigner.buildHeader(config, "put", path, param))).put(body).build();
|
|
|
|
+ Response response = client.newCall(request).execute();
|
|
|
|
+ if (!response.isSuccessful()) {
|
|
|
|
+ String error = response.body() != null ? new String(response.body().bytes(), StandardCharsets.UTF_8) : "";
|
|
|
|
+ throw new OssApiException(response.code(), error);
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
@Override
|
|
@Override
|
|
- public InputStream read(String path) {
|
|
|
|
- OSSObject ossObject = ossClient.getObject(bucket, formatPath(path));
|
|
|
|
- return ossObject.getObjectContent();
|
|
|
|
|
|
+ public InputStream read(String path) throws Exception {
|
|
|
|
+ path = formatPath(path);
|
|
|
|
+ OssApiParam param = new OssApiParam();
|
|
|
|
+ Request request = new Request.Builder().url(config.getEndpoint() + "/" + path)
|
|
|
|
+ .headers(buildHeader(param, OssSigner.buildHeader(config, "get", path, param))).get().build();
|
|
|
|
+ Response response = client.newCall(request).execute();
|
|
|
|
+ if (!response.isSuccessful()) {
|
|
|
|
+ String error = response.body() != null ? new String(response.body().bytes(), StandardCharsets.UTF_8) : "";
|
|
|
|
+ throw new OssApiException(response.code(), error);
|
|
|
|
+ } else {
|
|
|
|
+ return response.body() != null ? response.body().byteStream() : null;
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
@Override
|
|
@Override
|
|
- public boolean exist(String path) {
|
|
|
|
- try {
|
|
|
|
- return ossClient.doesObjectExist(bucket, formatPath(path));
|
|
|
|
- } catch (Exception e) {
|
|
|
|
|
|
+ public boolean exist(String path) throws IOException {
|
|
|
|
+ path = formatPath(path);
|
|
|
|
+ OssApiParam param = new OssApiParam();
|
|
|
|
+ Request request = new Request.Builder().url(config.getEndpoint() + "/" + path)
|
|
|
|
+ .headers(buildHeader(param, OssSigner.buildHeader(config, "head", path, param))).head().build();
|
|
|
|
+ Response response = client.newCall(request).execute();
|
|
|
|
+ if (response.isSuccessful()) {
|
|
|
|
+ return true;
|
|
|
|
+ } else if (response.code() == 404) {
|
|
return false;
|
|
return false;
|
|
|
|
+ } else {
|
|
|
|
+ String error = response.body() != null ? new String(response.body().bytes(), StandardCharsets.UTF_8) : "";
|
|
|
|
+ throw new OssApiException(response.code(), error);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@Override
|
|
@Override
|
|
- public boolean delete(String path) {
|
|
|
|
- ossClient.deleteObject(bucket, formatPath(path));
|
|
|
|
- return true;
|
|
|
|
|
|
+ public boolean delete(String path) throws IOException {
|
|
|
|
+ path = formatPath(path);
|
|
|
|
+ OssApiParam param = new OssApiParam();
|
|
|
|
+ Request request = new Request.Builder().url(config.getEndpoint() + "/" + path)
|
|
|
|
+ .headers(buildHeader(param, OssSigner.buildHeader(config, "delete", path, param))).delete().build();
|
|
|
|
+ Response response = client.newCall(request).execute();
|
|
|
|
+ if (response.code() != 200 && response.code() != 204) {
|
|
|
|
+ throw new OssApiException(response.code(), "");
|
|
|
|
+ } else {
|
|
|
|
+ return true;
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
@Override
|
|
@Override
|
|
- public void copy(String source, String target) throws Exception {
|
|
|
|
- ossClient.copyObject(bucket, formatPath(source), bucket, formatPath(target));
|
|
|
|
|
|
+ public String getPresignedUrl(String path, Duration expireDuration) {
|
|
|
|
+ path = formatPath(path);
|
|
|
|
+ return config.getPortal() + "/" + OssSigner.buildQuery(config, "get", path, expireDuration);
|
|
}
|
|
}
|
|
|
|
|
|
@Override
|
|
@Override
|
|
- public void close() {
|
|
|
|
- if (ossClient != null) {
|
|
|
|
- ossClient.shutdown();
|
|
|
|
- }
|
|
|
|
- if (temporaryUrlClient != null) {
|
|
|
|
- temporaryUrlClient.shutdown();
|
|
|
|
- }
|
|
|
|
|
|
+ public String getServer() {
|
|
|
|
+ return config.getPortal();
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
}
|