diff --git a/minio-plus-api-wrapper/minio-plus-api-wrapper-official/src/test/java/MinIORestful2.java b/minio-plus-api-wrapper/minio-plus-api-wrapper-official/src/test/java/MinIORestful2.java deleted file mode 100644 index 05b4f98..0000000 --- a/minio-plus-api-wrapper/minio-plus-api-wrapper-official/src/test/java/MinIORestful2.java +++ /dev/null @@ -1,317 +0,0 @@ -//import cn.hutool.core.collection.CollUtil; -//import cn.hutool.core.util.StrUtil; -//import cn.hutool.http.HttpRequest; -//import cn.hutool.http.HttpResponse; -//import cn.hutool.http.HttpUtil; -//import cn.hutool.http.Method; -//import com.google.common.base.Joiner; -//import com.google.common.collect.ImmutableSet; -//import com.google.common.collect.Multimap; -//import com.google.common.collect.MultimapBuilder; -//import com.google.common.io.BaseEncoding; -//import io.minio.PartSource; -//import io.minio.Signer; -//import io.minio.Xml; -//import io.minio.credentials.Credentials; -//import io.minio.errors.*; -//import io.minio.http.HttpUtils; -//import io.minio.messages.ErrorResponse; -//import okhttp3.*; -// -//import javax.crypto.Mac; -//import javax.crypto.spec.SecretKeySpec; -//import java.io.IOException; -//import java.io.PrintWriter; -//import java.nio.charset.StandardCharsets; -//import java.security.InvalidKeyException; -//import java.security.NoSuchAlgorithmException; -//import java.time.ZonedDateTime; -//import java.util.*; -//import java.util.stream.Collectors; -// -//public class MinIORestful2 { -// -// static final String serviceName = "s3"; -// static final String US_EAST_1 = "us-east-1"; -// private static final Set IGNORED_HEADERS = ImmutableSet.of("accept-encoding", "authorization", "content-type", "content-length", "user-agent"); -// -// static String accessKey = "minioadmin"; -// static String secretKey = "minioadmin"; -// static String ZERO_MD5_HASH = "1B2M2Y8AsgTpgAmY7PhCfg=="; -// static String ZERO_SHA256_HASH = "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"; -// static String backend = "http://localhost:9000"; -// -// public static void main(String[] args) throws NoSuchAlgorithmException, InvalidKeyException { -// -// // 动态传入参数 -// String url = "http://localhost:9000/document"; -// -// HttpResponse httpResponse = request(url,"","/document","head"); -// -// System.out.println("httpResponse.isOk()="+httpResponse.isOk()); -// System.out.println("httpResponse.getStatus()="+httpResponse.getStatus()); -// System.out.println("httpResponse.headers()="+httpResponse.headers()); -// System.out.println("httpResponse.body()="+httpResponse.body()); -// -// } -// -// public static HttpResponse request(String url,String params,String path,String method) throws NoSuchAlgorithmException, InvalidKeyException { -// -// // 取得当前时间 -// ZonedDateTime date = ZonedDateTime.now(); -// -// // 创建除Authorization外所有header -// Map> headers = new HashMap<>(); -// headers.put("Host", CollUtil.newArrayList(backend.replace("http://","").replace("https://",""))); -// headers.put("Accept-Encoding", CollUtil.newArrayList("identity")); -// headers.put("User-Agent", CollUtil.newArrayList("MinIO (Windows 10; amd64) minio-java/8.3.3")); -// headers.put("Content-MD5", CollUtil.newArrayList(ZERO_MD5_HASH)); -// headers.put("x-amz-content-sha256", CollUtil.newArrayList(ZERO_SHA256_HASH)); -// headers.put("x-amz-date", CollUtil.newArrayList(date.format(Time.AMZ_DATE_FORMAT))); -// -// // 计算scope -// String scope =buildScope(serviceName,date); -// -// // 计算signedHeaders -// Map canonicalHeaders = buildCanonicalHeaders(headers,IGNORED_HEADERS); -// -// // 计算signedHeaders -// String signedHeaders = buildSignedHeaders(canonicalHeaders); -// -// // 计算canonicalQueryString -// String canonicalQueryString = buildCanonicalQueryString(params); -// -// // 计算buildCanonicalRequest -// String canonicalRequestHash = buildCanonicalRequest(canonicalHeaders,signedHeaders,canonicalQueryString,method,path); -// -// // 计算stringToSign -// String stringToSign = buildStringToSign(date,scope,canonicalRequestHash); -// -// // 计算signingKey -// byte[] signingKey = buildSigningKey(serviceName,date); -// -// // 计算signature -// String signature = buildSignature(signingKey,stringToSign); -// -// // 计算authorization -// String authorization = buildAuthorization(accessKey,scope,signedHeaders,signature); -// -// HttpRequest httpRequest = HttpUtil.createRequest(Method.HEAD, url); -// httpRequest.header(headers,true); -// httpRequest.header("Authorization", authorization); -// -// -// -// System.out.println("scope="+scope); -// System.out.println("canonicalHeaders="+canonicalHeaders); -// System.out.println("signedHeaders="+signedHeaders); -// System.out.println("canonicalQueryString="+canonicalQueryString); -// System.out.println("canonicalRequestHash="+canonicalRequestHash); -// System.out.println("stringToSign="+stringToSign); -// System.out.println("signingKey="+signingKey); -// System.out.println("signature="+signature); -// System.out.println("authorization="+authorization); -// -// System.out.println("httpRequest.headers()="+httpRequest.headers()); -// -// return httpRequest.execute(); -// } -// -// -// protected void execute( -// io.minio.http.Method method, -// String bucketName, -// String objectName, -// String region, -// Headers headers, -// Multimap queryParamMap, -// Object body, -// int length) -// throws ErrorResponseException, InsufficientDataException, InternalException, -// InvalidKeyException, InvalidResponseException, IOException, NoSuchAlgorithmException, -// ServerException, XmlParserException { -// boolean traceRequestBody = false; -// if (body != null && !(body instanceof PartSource || body instanceof byte[])) { -// byte[] bytes; -// if (body instanceof CharSequence) { -// bytes = body.toString().getBytes(StandardCharsets.UTF_8); -// } else { -// bytes = Xml.marshal(body).getBytes(StandardCharsets.UTF_8); -// } -// -// body = bytes; -// length = bytes.length; -// traceRequestBody = true; -// } -// -// if (body == null && (method == io.minio.http.Method.PUT || method == io.minio.http.Method.POST)) -// body = HttpUtils.EMPTY_BODY; -// -// HttpUrl url = buildUrl(method, bucketName, objectName, region, queryParamMap); -// Credentials creds = (provider == null) ? null : provider.fetch(); -// Request request = createRequest(url, method, headers, body, length, creds); -// if (creds != null) { -// request = -// Signer.signV4S3( -// request, -// region, -// creds.accessKey(), -// creds.secretKey(), -// request.header("x-amz-content-sha256")); -// } -// -// StringBuilder traceBuilder = -// newTraceBuilder( -// request, traceRequestBody ? new String((byte[]) body, StandardCharsets.UTF_8) : null); -// PrintWriter traceStream = this.traceStream; -// if (traceStream != null) traceStream.println(traceBuilder.toString()); -// traceBuilder.append("\n"); -// -// OkHttpClient httpClient = this.httpClient; -// if (!(body instanceof byte[]) && (method == io.minio.http.Method.PUT || method == io.minio.http.Method.POST)) { -// // Issue #924: disable connection retry for PUT and POST methods for other than byte array. -// httpClient = this.httpClient.newBuilder().retryOnConnectionFailure(false).build(); -// } -// -// Response response = httpClient.newCall(request).execute(); -//// String trace = -//// response.protocol().toString().toUpperCase(Locale.US) -//// + " " -//// + response.code() -//// + "\n" -//// + response.headers(); -//// traceBuilder.append(trace).append("\n"); -//// if (traceStream != null) traceStream.println(trace); -//// -//// if (response.isSuccessful()) { -//// if (traceStream != null) { -//// // Trace response body only if the request is not GetObject/ListenBucketNotification S3 API. -//// Set keys = queryParamMap.keySet(); -//// if ((method != io.minio.http.Method.GET -//// || objectName == null -//// || !Collections.disjoint(keys, TRACE_QUERY_PARAMS)) -//// && !(keys.contains("events") && (keys.contains("prefix") || keys.contains("suffix")))) { -//// ResponseBody responseBody = response.peekBody(1024 * 1024); -//// traceStream.println(responseBody.string()); -//// } -//// traceStream.println(END_HTTP); -//// } -//// return response; -//// } -//// -//// String errorXml = null; -//// try (ResponseBody responseBody = response.body()) { -//// errorXml = responseBody.string(); -//// } -//// -//// if (!("".equals(errorXml) && method.equals(io.minio.http.Method.HEAD))) { -//// traceBuilder.append(errorXml).append("\n"); -//// if (traceStream != null) traceStream.println(errorXml); -//// } -//// -//// traceBuilder.append(END_HTTP).append("\n"); -//// if (traceStream != null) traceStream.println(END_HTTP); -//// -//// // Error in case of Non-XML response from server for non-HEAD requests. -//// String contentType = response.headers().get("content-type"); -//// if (!method.equals(io.minio.http.Method.HEAD) -//// && (contentType == null -//// || !Arrays.asList(contentType.split(";")).contains("application/xml"))) { -//// throw new InvalidResponseException( -//// response.code(), -//// contentType, -//// errorXml.substring(0, errorXml.length() > 1024 ? 1024 : errorXml.length()), -//// traceBuilder.toString()); -//// } -//// -//// ErrorResponse errorResponse = null; -//// if (!"".equals(errorXml)) { -//// errorResponse = Xml.unmarshal(ErrorResponse.class, errorXml); -//// } else if (!method.equals(io.minio.http.Method.HEAD)) { -//// throw new InvalidResponseException( -//// response.code(), contentType, errorXml, traceBuilder.toString()); -//// } -//// -//// if (errorResponse == null) { -//// String code = null; -//// String message = null; -//// switch (response.code()) { -//// case 301: -//// case 307: -//// case 400: -//// String[] result = handleRedirectResponse(method, bucketName, response, true); -//// code = result[0]; -//// message = result[1]; -//// break; -//// case 404: -//// if (objectName != null) { -//// code = "NoSuchKey"; -//// message = "Object does not exist"; -//// } else if (bucketName != null) { -//// code = NO_SUCH_BUCKET; -//// message = NO_SUCH_BUCKET_MESSAGE; -//// } else { -//// code = "ResourceNotFound"; -//// message = "Request resource not found"; -//// } -//// break; -//// case 501: -//// case 405: -//// code = "MethodNotAllowed"; -//// message = "The specified method is not allowed against this resource"; -//// break; -//// case 409: -//// if (bucketName != null) { -//// code = NO_SUCH_BUCKET; -//// message = NO_SUCH_BUCKET_MESSAGE; -//// } else { -//// code = "ResourceConflict"; -//// message = "Request resource conflicts"; -//// } -//// break; -//// case 403: -//// code = "AccessDenied"; -//// message = "Access denied"; -//// break; -//// case 412: -//// code = "PreconditionFailed"; -//// message = "At least one of the preconditions you specified did not hold"; -//// break; -//// case 416: -//// code = "InvalidRange"; -//// message = "The requested range cannot be satisfied"; -//// break; -//// default: -//// if (response.code() >= 500) { -//// throw new ServerException( -//// "server failed with HTTP status code " + response.code(), traceBuilder.toString()); -//// } -//// -//// throw new InternalException( -//// "unhandled HTTP code " -//// + response.code() -//// + ". Please report this issue at " -//// + "https://github.com/minio/minio-java/issues", -//// traceBuilder.toString()); -//// } -//// -//// errorResponse = -//// new ErrorResponse( -//// code, -//// message, -//// bucketName, -//// objectName, -//// request.url().encodedPath(), -//// response.header("x-amz-request-id"), -//// response.header("x-amz-id-2")); -//// } -//// -//// // invalidate region cache if needed -//// if (errorResponse.code().equals(NO_SUCH_BUCKET) || errorResponse.code().equals(RETRY_HEAD)) { -//// regionCache.remove(bucketName); -//// } -//// -//// throw new ErrorResponseException(errorResponse, response, traceBuilder.toString()); -// } -// -//} \ No newline at end of file diff --git a/minio-plus-core/src/main/java/org/liuxp/minioplus/core/repository/impl/MinioRepositoryImpl.java b/minio-plus-core/src/main/java/org/liuxp/minioplus/core/repository/impl/MinioRepositoryImpl.java index 7f25824..a876b92 100644 --- a/minio-plus-core/src/main/java/org/liuxp/minioplus/core/repository/impl/MinioRepositoryImpl.java +++ b/minio-plus-core/src/main/java/org/liuxp/minioplus/core/repository/impl/MinioRepositoryImpl.java @@ -85,7 +85,9 @@ public class MinioRepositoryImpl implements MinioRepository { @Override public ObjectWriteResponse completeMultipartUpload(MultipartUploadCreateDTO multipartUploadCreate) { try { - return this.getClient().completeMultipartUpload(multipartUploadCreate.getBucketName(), multipartUploadCreate.getRegion(), multipartUploadCreate.getObjectName(), multipartUploadCreate.getUploadId(), multipartUploadCreate.getParts(), multipartUploadCreate.getHeaders(), multipartUploadCreate.getExtraQueryParams()); + return this.getClient().completeMultipartUpload(multipartUploadCreate.getBucketName(), multipartUploadCreate.getRegion() + , multipartUploadCreate.getObjectName(), multipartUploadCreate.getUploadId(), multipartUploadCreate.getParts(), multipartUploadCreate.getHeaders() + , multipartUploadCreate.getExtraQueryParams()); } catch (Exception e) { log.error(MinioPlusErrorCode.COMPLETE_MULTIPART_FAILED.getMessage()+",uploadId:{},ObjectName:{},失败原因:{},", multipartUploadCreate.getUploadId(), multipartUploadCreate.getObjectName(), e.getMessage(), e); throw new MinioPlusException(MinioPlusErrorCode.COMPLETE_MULTIPART_FAILED); diff --git a/minio-plus-api-wrapper/minio-plus-api-wrapper-custom/pom.xml b/minio-s3-api/minio-s3-api-custom/pom.xml similarity index 59% rename from minio-plus-api-wrapper/minio-plus-api-wrapper-custom/pom.xml rename to minio-s3-api/minio-s3-api-custom/pom.xml index 250ef1a..61360fe 100644 --- a/minio-plus-api-wrapper/minio-plus-api-wrapper-custom/pom.xml +++ b/minio-s3-api/minio-s3-api-custom/pom.xml @@ -3,14 +3,19 @@ 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"> - minio-plus-api-wrapper + minio-s3-api org.liuxp ${revision} 4.0.0 - minio-plus-api-wrapper-custom - + minio-s3-api-custom + + + cn.hutool + hutool-all + + \ No newline at end of file diff --git a/minio-plus-api-wrapper/minio-plus-api-wrapper-official/src/test/java/MinIORestful.java b/minio-s3-api/minio-s3-api-custom/src/test/java/MinIORestful.java similarity index 84% rename from minio-plus-api-wrapper/minio-plus-api-wrapper-official/src/test/java/MinIORestful.java rename to minio-s3-api/minio-s3-api-custom/src/test/java/MinIORestful.java index d671a83..1b7b0aa 100644 --- a/minio-plus-api-wrapper/minio-plus-api-wrapper-official/src/test/java/MinIORestful.java +++ b/minio-s3-api/minio-s3-api-custom/src/test/java/MinIORestful.java @@ -1,21 +1,16 @@ import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.HexUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.http.HttpRequest; import cn.hutool.http.HttpResponse; import cn.hutool.http.HttpUtil; import cn.hutool.http.Method; -import com.google.common.base.Joiner; -import com.google.common.collect.ImmutableSet; -import com.google.common.collect.Multimap; -import com.google.common.collect.MultimapBuilder; -import com.google.common.io.BaseEncoding; -import io.minio.Digest; - import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; import java.nio.charset.StandardCharsets; import java.security.InvalidKeyException; +import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.time.ZonedDateTime; import java.util.*; @@ -25,7 +20,10 @@ public class MinIORestful { static final String serviceName = "s3"; static final String US_EAST_1 = "us-east-1"; - private static final Set IGNORED_HEADERS = ImmutableSet.of("accept-encoding", "authorization", "content-type", "content-length", "user-agent"); + + + + private static final Set IGNORED_HEADERS = CollUtil.set(true,"accept-encoding", "authorization", "content-type", "content-length", "user-agent"); static String accessKey = "minioadmin"; static String secretKey = "minioadmin"; @@ -35,6 +33,8 @@ public class MinIORestful { public static void main(String[] args) throws NoSuchAlgorithmException, InvalidKeyException { + + // 动态传入参数 String url = "http://localhost:9000/document"; @@ -146,7 +146,7 @@ public class MinIORestful { * @return */ public static String buildSignedHeaders(Map canonicalHeaders) { - return Joiner.on(";").join(canonicalHeaders.keySet()); + return StrUtil.join(";", canonicalHeaders.keySet()); } public static String buildCanonicalQueryString(String params){ @@ -155,31 +155,51 @@ public class MinIORestful { return ""; } + return params; + + //TODO + +// MapUtil + // Building a multimap which only order keys, ordering values is not performed // until MinIO server supports it. - Multimap signedQueryParams = - MultimapBuilder.treeKeys().arrayListValues().build(); - - for (String queryParam : params.split("&")) { - String[] tokens = queryParam.split("="); - if (tokens.length > 1) { - signedQueryParams.put(tokens[0], tokens[1]); - } else { - signedQueryParams.put(tokens[0], ""); - } - } - - return Joiner.on("&").withKeyValueSeparator("=").join(signedQueryParams.entries()); +// Multimap signedQueryParams = +// MultimapBuilder.treeKeys().arrayListValues().build(); +// +// for (String queryParam : params.split("&")) { +// String[] tokens = queryParam.split("="); +// if (tokens.length > 1) { +// signedQueryParams.put(tokens[0], tokens[1]); +// } else { +// signedQueryParams.put(tokens[0], ""); +// } +// } +// +// return Joiner.on("&").withKeyValueSeparator("=").join(signedQueryParams.entries()); } public static String buildCanonicalRequest(Map canonicalHeaders,String signedHeaders ,String canonicalQueryString,String method,String path) throws NoSuchAlgorithmException { + StringBuilder headers = new StringBuilder(); + for (String key : canonicalHeaders.keySet()) { + + headers.append(key); + headers.append(":"); + headers.append(canonicalHeaders.get(key)); + headers.append("\n"); + } + String canonicalRequest = method + "\n" + path + "\n" + canonicalQueryString + "\n" - + Joiner.on("\n").withKeyValueSeparator(":").join(canonicalHeaders) + "\n\n" + signedHeaders + "\n" + ZERO_SHA256_HASH; + + headers + "\n" + signedHeaders + "\n" + ZERO_SHA256_HASH; System.out.println("canonicalRequest="+canonicalRequest); - return Digest.sha256Hash(canonicalRequest); + + byte[] data = canonicalRequest.getBytes(StandardCharsets.UTF_8); + MessageDigest sha256Digest = MessageDigest.getInstance("SHA-256"); + sha256Digest.update(data, 0, data.length); + + return HexUtil.encodeHexStr(sha256Digest.digest()); } /** @@ -217,7 +237,7 @@ public class MinIORestful { */ public static String buildSignature(byte[] signingKey,String stringToSign) throws NoSuchAlgorithmException, InvalidKeyException { byte[] digest = sumHmac(signingKey, stringToSign.getBytes(StandardCharsets.UTF_8)); - return BaseEncoding.base16().encode(digest).toLowerCase(Locale.US); + return HexUtil.encodeHexStr(digest); } /** diff --git a/minio-plus-api-wrapper/minio-plus-api-wrapper-official/src/test/java/Time.java b/minio-s3-api/minio-s3-api-custom/src/test/java/Time.java similarity index 100% rename from minio-plus-api-wrapper/minio-plus-api-wrapper-official/src/test/java/Time.java rename to minio-s3-api/minio-s3-api-custom/src/test/java/Time.java diff --git a/minio-s3-api/minio-s3-api-definition/pom.xml b/minio-s3-api/minio-s3-api-definition/pom.xml new file mode 100644 index 0000000..f1007f1 --- /dev/null +++ b/minio-s3-api/minio-s3-api-definition/pom.xml @@ -0,0 +1,21 @@ + + + + minio-s3-api + org.liuxp + ${revision} + + 4.0.0 + + minio-s3-api-definition + + + + org.projectlombok + lombok + + + + \ No newline at end of file diff --git a/minio-s3-api/minio-s3-api-definition/src/main/java/org/liuxp/minioplus/s3/def/ListParts.java b/minio-s3-api/minio-s3-api-definition/src/main/java/org/liuxp/minioplus/s3/def/ListParts.java new file mode 100644 index 0000000..8032c9c --- /dev/null +++ b/minio-s3-api/minio-s3-api-definition/src/main/java/org/liuxp/minioplus/s3/def/ListParts.java @@ -0,0 +1,52 @@ +package org.liuxp.minioplus.s3.def; + +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; + +import java.time.ZonedDateTime; +import java.util.ArrayList; +import java.util.List; + +@Getter +@Setter +@ToString +public class ListParts { + + private String bucketName; + + private String objectName; + + private int maxParts; + + private List partList = null; + + @Getter + @Setter + @ToString + static class Part{ + private int partNumber; + + private String etag; + + private ZonedDateTime lastModified; + + private Long size; + } + + ListParts addPart(int partNumber,String etag,ZonedDateTime lastModified,Long size){ + + Part part = new Part(); + part.setPartNumber(partNumber); + part.setEtag(etag); + part.setLastModified(lastModified); + part.setSize(size); + + if(this.partList == null){ + partList = new ArrayList<>(); + } + partList.add(part); + return this; + } + +} diff --git a/minio-s3-api/minio-s3-api-definition/src/main/java/org/liuxp/minioplus/s3/def/MinioS3Client.java b/minio-s3-api/minio-s3-api-definition/src/main/java/org/liuxp/minioplus/s3/def/MinioS3Client.java new file mode 100644 index 0000000..c9c8637 --- /dev/null +++ b/minio-s3-api/minio-s3-api-definition/src/main/java/org/liuxp/minioplus/s3/def/MinioS3Client.java @@ -0,0 +1,110 @@ +package org.liuxp.minioplus.s3.def; + +import java.io.InputStream; +import java.util.List; +import java.util.Map; + +/** + * MinIO S3文件存储引擎接口定义 + * + * @author contact@liuxp.me + * @since 2024/06/03 + */ +public interface MinioS3Client { + + /** + * 判断存储桶是否存在 + * @param bucketName 桶名称 + * @return 是否存在 + */ + Boolean bucketExists(String bucketName); + + /** + * 创建桶 + * @param bucketName 桶名称 + */ + void makeBucket(String bucketName); + + /** + * 创建上传任务 + * @param bucketName 桶名称 + * @param objectName 对象名称(含路径) + * @return UploadId 上传任务编号 + */ + String createMultipartUpload(String bucketName, String objectName); + + /** + * 合并分片 + * @param bucketName 桶名称 + * @param objectName 对象名称(含路径) + * @param uploadId 上传任务编号 + * @param parts 分片信息 partNumber & etag + * @return 是否成功 + */ + Boolean completeMultipartUpload(String bucketName, String objectName, String uploadId, List parts); + + /** + * 获取分片信息列表 + * @param bucketName 桶名称 + * @param objectName 对象名称(含路径) + * @param maxParts 分片数量 + * @param uploadId 上传任务编号 + * @return 分片信息 + */ + ListParts listParts(String bucketName,String objectName,Integer maxParts,String uploadId); + + /** + * 获得对象&分片上传链接 + * @param bucketName 桶名称 + * @param objectName 对象名称(含路径) + * @param partNumber 分片序号 + * @return {@link String} + */ + String getUploadObjectUrl(String bucketName, String objectName, String partNumber); + + /** + * 取得下载链接 + * @param fileName 文件全名含扩展名 + * @param contentType 数据类型 + * @param bucketName 桶名称 + * @param objectName 对象名称含路径 + * @return 下载地址 + */ + String getDownloadUrl(String fileName, String contentType, String bucketName, String objectName); + + /** + * 取得图片预览链接 + * @param contentType 数据类型 + * @param bucketName 桶名称 + * @param objectName 对象名称含路径 + * @return 图片预览链接 + */ + String getPreviewUrl(String contentType, String bucketName, String objectName); + + /** + * 写入文件 + * @param bucketName 桶名称 + * @param objectName 对象名称含路径 + * @param stream 文件流 + * @param size 文件长度 + * @param contentType 文件类型 + * @return 是否成功 + */ + Boolean putObject(String bucketName, String objectName, InputStream stream, long size, String contentType); + + /** + * 读取文件 + * @param bucketName 桶名称 + * @param objectName 对象名称含路径 + * @return 文件流 + */ + byte[] getObject(String bucketName, String objectName); + + /** + * 删除文件 + * @param bucketName 桶名称 + * @param objectName 对象名称含路径 + */ + void removeObject(String bucketName, String objectName); + +} \ No newline at end of file diff --git a/minio-plus-api-wrapper/minio-plus-api-wrapper-official/pom.xml b/minio-s3-api/minio-s3-api-official/pom.xml similarity index 79% rename from minio-plus-api-wrapper/minio-plus-api-wrapper-official/pom.xml rename to minio-s3-api/minio-s3-api-official/pom.xml index c45b191..befc8e2 100644 --- a/minio-plus-api-wrapper/minio-plus-api-wrapper-official/pom.xml +++ b/minio-s3-api/minio-s3-api-official/pom.xml @@ -3,13 +3,13 @@ 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"> - minio-plus-api-wrapper + minio-s3-api org.liuxp ${revision} 4.0.0 - minio-plus-api-wrapper-official + minio-s3-api-official @@ -28,10 +28,6 @@ okhttp 4.11.0 - - cn.hutool - hutool-all - \ No newline at end of file diff --git a/minio-plus-api-wrapper/minio-plus-api-wrapper-official/src/test/java/Digest.java b/minio-s3-api/minio-s3-api-official/src/test/java/Digest.java similarity index 100% rename from minio-plus-api-wrapper/minio-plus-api-wrapper-official/src/test/java/Digest.java rename to minio-s3-api/minio-s3-api-official/src/test/java/Digest.java diff --git a/minio-plus-api-wrapper/minio-plus-api-wrapper-official/src/test/java/S3Base.java b/minio-s3-api/minio-s3-api-official/src/test/java/S3Base.java similarity index 100% rename from minio-plus-api-wrapper/minio-plus-api-wrapper-official/src/test/java/S3Base.java rename to minio-s3-api/minio-s3-api-official/src/test/java/S3Base.java diff --git a/minio-plus-api-wrapper/minio-plus-api-wrapper-official/src/test/java/S3Escaper.java b/minio-s3-api/minio-s3-api-official/src/test/java/S3Escaper.java similarity index 100% rename from minio-plus-api-wrapper/minio-plus-api-wrapper-official/src/test/java/S3Escaper.java rename to minio-s3-api/minio-s3-api-official/src/test/java/S3Escaper.java diff --git a/minio-plus-api-wrapper/minio-plus-api-wrapper-official/src/test/java/Signer.java b/minio-s3-api/minio-s3-api-official/src/test/java/Signer.java similarity index 100% rename from minio-plus-api-wrapper/minio-plus-api-wrapper-official/src/test/java/Signer.java rename to minio-s3-api/minio-s3-api-official/src/test/java/Signer.java diff --git a/minio-s3-api/minio-s3-api-official/src/test/java/Time.java b/minio-s3-api/minio-s3-api-official/src/test/java/Time.java new file mode 100644 index 0000000..61d351b --- /dev/null +++ b/minio-s3-api/minio-s3-api-official/src/test/java/Time.java @@ -0,0 +1,44 @@ +/* + * MinIO Java SDK for Amazon S3 Compatible Cloud Storage, + * (C) 2020 MinIO, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import java.time.ZoneId; +import java.time.format.DateTimeFormatter; +import java.util.Locale; + +/** Time formatters for S3 APIs. */ +public class Time { + public static final ZoneId UTC = ZoneId.of("Z"); + + public static final DateTimeFormatter AMZ_DATE_FORMAT = + DateTimeFormatter.ofPattern("yyyyMMdd'T'HHmmss'Z'", Locale.US).withZone(UTC); + + public static final DateTimeFormatter RESPONSE_DATE_FORMAT = + DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH':'mm':'ss'.'SSS'Z'", Locale.US).withZone(UTC); + + // Formatted string is convertible to LocalDate only, not to LocalDateTime or ZonedDateTime. + // Below example shows how to use this to get ZonedDateTime. + // LocalDate.parse("20200225", SIGNER_DATE_FORMAT).atStartOfDay(UTC); + public static final DateTimeFormatter SIGNER_DATE_FORMAT = + DateTimeFormatter.ofPattern("yyyyMMdd", Locale.US).withZone(UTC); + + public static final DateTimeFormatter HTTP_HEADER_DATE_FORMAT = + DateTimeFormatter.ofPattern("EEE',' dd MMM yyyy HH':'mm':'ss 'GMT'", Locale.US).withZone(UTC); + + public static final DateTimeFormatter EXPIRATION_DATE_FORMAT = RESPONSE_DATE_FORMAT; + + private Time() {} +} diff --git a/minio-plus-api-wrapper/pom.xml b/minio-s3-api/pom.xml similarity index 72% rename from minio-plus-api-wrapper/pom.xml rename to minio-s3-api/pom.xml index 5d84d8e..428b44d 100644 --- a/minio-plus-api-wrapper/pom.xml +++ b/minio-s3-api/pom.xml @@ -9,12 +9,13 @@ 4.0.0 - minio-plus-api-wrapper + minio-s3-api pom - minio-plus-api-wrapper-custom - minio-plus-api-wrapper-official + minio-s3-api-definition + minio-s3-api-custom + minio-s3-api-official \ No newline at end of file diff --git a/pom.xml b/pom.xml index 6084a71..d011f7e 100644 --- a/pom.xml +++ b/pom.xml @@ -35,7 +35,6 @@ - minio-plus-api-wrapper minio-plus-application minio-plus-common minio-plus-config @@ -43,6 +42,7 @@ minio-plus-extension minio-plus-model minio-plus-spring-boot-starter + minio-s3-api