| | |
| | | import software.amazon.awssdk.auth.credentials.AwsBasicCredentials; |
| | | import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider; |
| | | import software.amazon.awssdk.core.ResponseInputStream; |
| | | import software.amazon.awssdk.core.async.AsyncRequestBody; |
| | | import software.amazon.awssdk.core.async.AsyncResponseTransformer; |
| | | import software.amazon.awssdk.core.async.BlockingInputStreamAsyncRequestBody; |
| | | import software.amazon.awssdk.regions.Region; |
| | | import software.amazon.awssdk.services.s3.S3AsyncClient; |
| | | import software.amazon.awssdk.services.s3.S3Configuration; |
| | | import software.amazon.awssdk.services.s3.crt.S3CrtHttpConfiguration; |
| | | import software.amazon.awssdk.services.s3.model.GetObjectResponse; |
| | | import software.amazon.awssdk.services.s3.model.NoSuchBucketException; |
| | | import software.amazon.awssdk.services.s3.model.S3Exception; |
| | |
| | | StaticCredentialsProvider credentialsProvider = StaticCredentialsProvider.create( |
| | | AwsBasicCredentials.create(properties.getAccessKey(), properties.getSecretKey())); |
| | | |
| | | //MinIO 使用 HTTPS 限制使用域名访问,站点填域名。需要启用路径样式访问 |
| | | boolean isStyle = !StringUtils.containsAny(properties.getEndpoint(), OssConstant.CLOUD_SERVICE); |
| | | //使用对象存储服务时要求明确配置访问样式(路径样式或虚拟托管样式)。需要启用路径样式访问 |
| | | boolean isStyle = true; |
| | | |
| | | //创建AWS基于 CRT 的 S3 客户端 |
| | | this.client = S3AsyncClient.crtBuilder() |
| | |
| | | .minimumPartSizeInBytes(10 * 1025 * 1024L) |
| | | .checksumValidationEnabled(false) |
| | | .forcePathStyle(isStyle) |
| | | .httpConfiguration(S3CrtHttpConfiguration.builder() |
| | | .connectionTimeout(Duration.ofSeconds(60)) // 设置连接超时 |
| | | .build()) |
| | | .build(); |
| | | |
| | | //AWS基于 CRT 的 S3 AsyncClient 实例用作 S3 传输管理器的底层客户端 |
| | |
| | | /** |
| | | * 上传文件到 Amazon S3,并返回上传结果 |
| | | * |
| | | * @param filePath 本地文件路径 |
| | | * @param key 在 Amazon S3 中的对象键 |
| | | * @param md5Digest 本地文件的 MD5 哈希值(可选) |
| | | * @param filePath 本地文件路径 |
| | | * @param key 在 Amazon S3 中的对象键 |
| | | * @param md5Digest 本地文件的 MD5 哈希值(可选) |
| | | * @param contentType 文件内容类型 |
| | | * @return UploadResult 包含上传后的文件信息 |
| | | * @throws OssException 如果上传失败,抛出自定义异常 |
| | | */ |
| | | public UploadResult upload(Path filePath, String key, String md5Digest) { |
| | | public UploadResult upload(Path filePath, String key, String md5Digest, String contentType) { |
| | | try { |
| | | // 构建上传请求对象 |
| | | FileUpload fileUpload = transferManager.uploadFile( |
| | |
| | | y -> y.bucket(properties.getBucketName()) |
| | | .key(key) |
| | | .contentMD5(StringUtils.isNotEmpty(md5Digest) ? md5Digest : null) |
| | | .contentType(contentType) |
| | | // 用于设置对象的访问控制列表(ACL)。不同云厂商对ACL的支持和实现方式有所不同, |
| | | // 因此根据具体的云服务提供商,你可能需要进行不同的配置(自行开启,阿里云有acl权限配置,腾讯云没有acl权限配置) |
| | | //.acl(getAccessPolicy().getObjectCannedACL()) |
| | | .build()) |
| | | .addTransferListener(LoggingTransferListener.create()) |
| | | .source(filePath).build()); |
| | |
| | | * @param inputStream 要上传的输入流 |
| | | * @param key 在 Amazon S3 中的对象键 |
| | | * @param length 输入流的长度 |
| | | * @param contentType 文件内容类型 |
| | | * @return UploadResult 包含上传后的文件信息 |
| | | * @throws OssException 如果上传失败,抛出自定义异常 |
| | | */ |
| | | public UploadResult upload(InputStream inputStream, String key, Long length) { |
| | | public UploadResult upload(InputStream inputStream, String key, Long length, String contentType) { |
| | | // 如果输入流不是 ByteArrayInputStream,则将其读取为字节数组再创建 ByteArrayInputStream |
| | | if (!(inputStream instanceof ByteArrayInputStream)) { |
| | | inputStream = new ByteArrayInputStream(IoUtil.readBytes(inputStream)); |
| | | } |
| | | try { |
| | | // 创建异步请求体(length如果为空会报错) |
| | | BlockingInputStreamAsyncRequestBody body = AsyncRequestBody.forBlockingInputStream(length); |
| | | BlockingInputStreamAsyncRequestBody body = BlockingInputStreamAsyncRequestBody.builder() |
| | | .contentLength(length) |
| | | .subscribeTimeout(Duration.ofSeconds(30)) |
| | | .build(); |
| | | |
| | | // 使用 transferManager 进行上传 |
| | | Upload upload = transferManager.upload( |
| | |
| | | .putObjectRequest( |
| | | y -> y.bucket(properties.getBucketName()) |
| | | .key(key) |
| | | .contentType(contentType) |
| | | // 用于设置对象的访问控制列表(ACL)。不同云厂商对ACL的支持和实现方式有所不同, |
| | | // 因此根据具体的云服务提供商,你可能需要进行不同的配置(自行开启,阿里云有acl权限配置,腾讯云没有acl权限配置) |
| | | //.acl(getAccessPolicy().getObjectCannedACL()) |
| | | .build()) |
| | | .build()); |
| | | |
| | |
| | | * @return UploadResult 包含上传后的文件信息 |
| | | * @throws OssException 如果上传失败,抛出自定义异常 |
| | | */ |
| | | public UploadResult uploadSuffix(byte[] data, String suffix) { |
| | | return upload(new ByteArrayInputStream(data), getPath(properties.getPrefix(), suffix), Long.valueOf(data.length)); |
| | | public UploadResult uploadSuffix(byte[] data, String suffix, String contentType) { |
| | | return upload(new ByteArrayInputStream(data), getPath(properties.getPrefix(), suffix), Long.valueOf(data.length), contentType); |
| | | } |
| | | |
| | | /** |
| | |
| | | * @return UploadResult 包含上传后的文件信息 |
| | | * @throws OssException 如果上传失败,抛出自定义异常 |
| | | */ |
| | | public UploadResult uploadSuffix(InputStream inputStream, String suffix, Long length) { |
| | | return upload(inputStream, getPath(properties.getPrefix(), suffix), length); |
| | | public UploadResult uploadSuffix(InputStream inputStream, String suffix, Long length, String contentType) { |
| | | return upload(inputStream, getPath(properties.getPrefix(), suffix), length, contentType); |
| | | } |
| | | |
| | | /** |
| | |
| | | * @throws OssException 如果上传失败,抛出自定义异常 |
| | | */ |
| | | public UploadResult uploadSuffix(File file, String suffix) { |
| | | return upload(file.toPath(), getPath(properties.getPrefix(), suffix), null); |
| | | return upload(file.toPath(), getPath(properties.getPrefix(), suffix), null, FileUtils.getMimeType(suffix)); |
| | | } |
| | | |
| | | /** |