package com.iplatform.file.support; import com.amazonaws.ClientConfiguration; import com.amazonaws.Protocol; import com.amazonaws.auth.AWSCredentials; import com.amazonaws.auth.AWSStaticCredentialsProvider; import com.amazonaws.auth.BasicAWSCredentials; import com.amazonaws.auth.policy.Policy; import com.amazonaws.auth.policy.Principal; import com.amazonaws.auth.policy.Resource; import com.amazonaws.auth.policy.Statement; import com.amazonaws.auth.policy.actions.S3Actions; import com.amazonaws.client.builder.AwsClientBuilder; import com.amazonaws.regions.Regions; import com.amazonaws.services.s3.AmazonS3; import com.amazonaws.services.s3.AmazonS3ClientBuilder; import com.amazonaws.services.s3.model.BucketCrossOriginConfiguration; import com.amazonaws.services.s3.model.CORSRule; import com.amazonaws.services.s3.model.ObjectMetadata; import com.amazonaws.services.s3.model.PutObjectRequest; import com.amazonaws.services.s3.model.PutObjectResult; import com.amazonaws.services.s3.model.S3Object; import com.amazonaws.services.s3.model.S3ObjectInputStream; import com.amazonaws.services.s3.model.SetBucketPolicyRequest; import com.walker.file.DefaultFileInfo; import com.walker.file.FileInfo; import com.walker.file.FileOperateException; import com.walker.file.FileStoreType; import com.walker.infrastructure.utils.Base64; import com.walker.infrastructure.utils.JsonUtils; import com.walker.infrastructure.utils.StringUtils; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.util.Arrays; import java.util.Calendar; /** * 亚马逊S3 OSS 实现。 * * @author 时克英 * @date 2023-12-12 */ public class AwsOssFileEngine extends AbstractOssFileEngine { public AwsOssFileEngine() { } @Override protected void executeUpload(InputStream inputStream, FileInfo fileInfo) throws FileOperateException { //初始化对象元数据 ObjectMetadata metadata = new ObjectMetadata(); // metadata.setContentType("plain/text"); AmazonS3 client = this.acquireOneClient(); try { String fileNameBase64 = new String(Base64.encode(fileInfo.getFileName().getBytes(StringUtils.DEFAULT_CHARSET_UTF8))); metadata.addUserMetadata("x-amz-meta-title", fileNameBase64); metadata.setContentLength(fileInfo.getFileSize()); //设置对象元数据 String objectKey = fileInfo.getId(); logger.debug("准备上传文件 objectKey = {}", objectKey); // String objectKey = createFileOssPath(fileInfo.getId(), fileInfo.getFileExt()); PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, objectKey, inputStream, metadata); // PutObjectResult result = amazonS3Client.putObject(putObjectRequest); PutObjectResult result = client.putObject(putObjectRequest); System.out.println(JsonUtils.objectToJsonString(result)); StringBuilder url = new StringBuilder(); url.append(objectKey); // ((DefaultFileInfo) fileInfo).setFileSize(result.getMetadata().getContentLength()); ((DefaultFileInfo) fileInfo).setUrl(url.toString()); } catch (Exception var11) { throw new FileOperateException("保存文件到【oss】错误:" + var11.getMessage() + ", id=" + fileInfo.getId(), var11); } finally { if(client != null){ client.shutdown(); } } } @Override protected byte[] executeDownload(FileInfo fileInfo) throws FileOperateException { // throw new IllegalAccessError("不能调用OSS下载方法,请访问第三方链接"); AmazonS3 client = this.acquireOneClient(); S3ObjectInputStream objectContent = null; ByteArrayOutputStream fileOutputStream = null; try { //下载对象 S3Object object = client.getObject(bucketName, fileInfo.getId()); //获取对象流 objectContent = object.getObjectContent(); //初始化文件输出流 // FileOutputStream fileOutputStream = new FileOutputStream(new File(file_path)); fileOutputStream = new ByteArrayOutputStream(); byte[] readbuf = new byte[1024 * 20]; int read_len = 0; while ((read_len = objectContent.read(readbuf)) > 0) { //对象下载字节写入文件输出流 fileOutputStream.write(readbuf, 0, read_len); } return fileOutputStream.toByteArray(); } catch (Exception ex) { throw new FileOperateException("下载文件错误:" + ex.getMessage() + ", fileId=" + fileInfo.getId(), ex); } finally { //关闭流 try { if(objectContent != null){ objectContent.close(); } // if(fileOutputStream != null){ // fileOutputStream.close(); // } if(client != null){ client.shutdown(); } } catch (IOException e) { // throw new RuntimeException(e); logger.error("这里不需要抛出异常,仅用于调试知道流没有被关闭即可。", e); } } } @Override public FileStoreType getFileStoreType() { return FileStoreType.OssAws; } @Override public void close() { super.close(); this.closeAmazonS3Client(); } private AmazonS3 acquireOneClient(){ AWSCredentials credentials = new BasicAWSCredentials(accessKey, secretKey); ClientConfiguration clientConfiguration = new ClientConfiguration(); if (endpoint.contains("https")) { clientConfiguration.setProtocol(Protocol.HTTPS); logger.error("===================> HTTPS "); } else { clientConfiguration.setProtocol(Protocol.HTTP); logger.error("===================> HTTP "); } return AmazonS3ClientBuilder.standard() .withClientConfiguration(clientConfiguration) .withEndpointConfiguration( new AwsClientBuilder.EndpointConfiguration(this.endpoint, Regions.DEFAULT_REGION.getName())) .withCredentials(new AWSStaticCredentialsProvider(credentials)) .build(); // AmazonS3 amazonS3Client = new AmazonS3Client(credentials, clientConfiguration); // amazonS3Client.setEndpoint(endpoint); // amazonS3Client.setS3ClientOptions(S3ClientOptions.builder().setPathStyleAccess(true).disableChunkedEncoding().build()); // return amazonS3Client; } /** * 初始化amazonS3Client * @author 时克英 * @date 2024-02-02 使用多例,无需初始化,废弃方法。 */ @Deprecated public void initS3Client() { logger.warn("不再使用单例,无需初始化,每次上传下载会创建新客户端连接!"); // AWSCredentials credentials = new BasicAWSCredentials(accessKey, secretKey); //创建AWS凭证 // ClientConfiguration connconfig = new ClientConfiguration(); //初始化客户端config // connconfig.setProtocol(Protocol.HTTP); //设置mos 请求协议为http // // //使用AWS凭证和clientConfiguration初始化AmazonS3Client客户端 // amazonS3Client = new AmazonS3Client(credentials, connconfig); // amazonS3Client.setEndpoint(endpoint); ////设置mos对象服务接口地址 // amazonS3Client.setS3ClientOptions(S3ClientOptions.builder().setPathStyleAccess(true).disableChunkedEncoding().build()); // AWSCredentials credentials = new BasicAWSCredentials(accessKey, secretKey); // ClientConfiguration clientConfiguration = new ClientConfiguration(); // // if (endpoint.contains("https")) { // clientConfiguration.setProtocol(Protocol.HTTPS); // logger.error("===================> HTTPS "); // } else { // clientConfiguration.setProtocol(Protocol.HTTP); // logger.error("===================> HTTP "); // } // // AwsClientBuilder.EndpointConfiguration endpointConfiguration = new AwsClientBuilder.EndpointConfiguration(endpoint, "beijing1"); // AWSCredentialsProvider credentialsProvider = new AWSStaticCredentialsProvider(credentials); // // // amazonS3Client = AmazonS3ClientBuilder.standard() // .withEndpointConfiguration(endpointConfiguration) // .withCredentials(credentialsProvider).build(); //// amazonS3Client = new AmazonS3Client(credentials, clientConfiguration); //// amazonS3Client.setEndpoint(endpoint); //// amazonS3Client.setS3ClientOptions(S3ClientOptions.builder().setPathStyleAccess(true).disableChunkedEncoding().build()); AWSCredentials credentials = new BasicAWSCredentials(accessKey, secretKey); ClientConfiguration clientConfiguration = new ClientConfiguration(); if (endpoint.contains("https")) { clientConfiguration.setProtocol(Protocol.HTTPS); logger.error("===================> HTTPS "); } else { clientConfiguration.setProtocol(Protocol.HTTP); logger.error("===================> HTTP "); } // 设置允许打开的最大 HTTP 连接数,默认为 50 个,此示例代码设置为 100 个。 // clientConfiguration.setMaxConnections(100 * 2); // // 设置 Socket 层传输数据的超时时间(单位:毫秒),默认为 50000 毫秒,此示例代码设置为 60000 毫秒。 // clientConfiguration.setSocketTimeout(60000 * 2); // // 设置建立连接的超时时间(单位:毫秒),默认为 10000 毫秒,此示例代码设置为 5000 毫秒。 // clientConfiguration.setConnectionTimeout(5000 * 2); // // 设置等待请求完成的超时时间(单位:毫秒)。默认不超时(0),此示例代码设置为 60000 毫秒。 // clientConfiguration.setRequestTimeout(60000 * 2); // // 设置客户端请求执行超时时间(单位:毫秒)。默认不超时(0),此示例代码设置为 60000 毫秒。 // clientConfiguration.setClientExecutionTimeout(60000 * 2); // // 设置连接空闲超时时间。超时则关闭连接,默认为 60000 毫秒,此示例代码设置为 90000 毫秒。 //// clientConfiguration.setConnectionMaxIdleMillis(90000 * 2); // // 设置请求失败后最大的重试次数,默认 3 次,此示例代码设置为 5 次。 // clientConfiguration.setMaxErrorRetry(5); // 设置连接 EOS 所使用的协议(HTTP 或 HTTPS),默认为 HTTPS,此示例代码设置为 HTTP。 // clientConfiguration.setProtocol(Protocol.HTTP); // 设置用户代理前缀,即 HTTP 的 User-Agent 头的前缀,此示例代码设置为 "EOS S3 Java SDK"。 // clientConfiguration.setUserAgentPrefix("EOS S3 Java SDK"); // 设置用户代理后缀,即 HTTP 的 User-Agent 头的后缀,此示例代码设置为 "1.12.378"。 // clientConfiguration.setUserAgentSuffix("1.12.378"); // 设置签名算法,默认为 v4 签名。此示例代码设置为 S3SignerType,即采用 v2 签名。 // clientConfiguration.setSignerOverride("S3SignerType"); // 2024-02-02,不用单例,使用多例即:每次调用创建客户端方式! // amazonS3Client = new AmazonS3Client(credentials, clientConfiguration); // amazonS3Client.setEndpoint(endpoint); // amazonS3Client.setS3ClientOptions(S3ClientOptions.builder().setPathStyleAccess(true).disableChunkedEncoding().build()); } /** * 对应MOS JAVA SDK文档4.3.6章节 设置存储桶策略 */ @Deprecated public void setBucketPolicy() throws IOException { // List readLines = Files.readLines(new File("policy.txt"), Charset.forName("utf8")); // StringBuilder sb = new StringBuilder(); // for(String str : readLines) // { // sb.append(str); // } // System.out.println(sb.toString()); // // //policy 信息查看项目根目录 policy.txt文件 // String policy = sb.toString(); // amazonS3Client.setBucketPolicy(bucket_name, policy); //通过Policy类构建桶策略 Policy bucket_policy = new Policy().withStatements(new Statement( Statement.Effect.Allow) .withPrincipals(Principal.AllUsers) .withActions(S3Actions.GetObject) .withResources( new Resource("arn:aws:s3:::" + bucketName + "/*"))); SetBucketPolicyRequest setBucketPolicyRequest = new SetBucketPolicyRequest(bucketName, bucket_policy.toJson()); //设置桶策略 // amazonS3Client.setBucketPolicy(setBucketPolicyRequest); } @Deprecated public void configBucketCors() { // 配置跨域访问策略 BucketCrossOriginConfiguration conf = new BucketCrossOriginConfiguration() .withRules( new CORSRule() .withId("1")// 配置规则 ID .withAllowedHeaders(Arrays.asList("*")) // 跨域请求可以使用的 HTTP 请求头部,支持通配符 * .withAllowedMethods(Arrays.asList(CORSRule.AllowedMethods.GET, CORSRule.AllowedMethods.PUT))// 跨域请求允许的 HTTP 操作,例如:GET,PUT,HEAD,POST,DELETE // .withAllowedOrigins(Arrays.asList("http://www.example1.com"))// 允许的访问来源,支持通配符 *,格式为:协议://域名[:端口] // .withMaxAgeSeconds(30)// 跨域请求得到结果的有效期 ); // SetBucketCrossOriginConfigurationRequest req = new SetBucketCrossOriginConfigurationRequest("bkt", conf); // amazonS3Client.setBucketCrossOriginConfiguration(req); // 删除跨域访问策略 // amazonS3Client.deleteBucketCrossOriginConfiguration("1"); } /** * 关闭amazonS3Client */ private void closeAmazonS3Client() { // if (this.amazonS3Client != null) { // amazonS3Client.shutdown(); //关闭客户端 // } } public byte[] testDownload(String fileId){ DefaultFileInfo fileInfo = new DefaultFileInfo(); fileInfo.setId(fileId); try { return this.executeDownload(fileInfo); } catch (FileOperateException e) { throw new RuntimeException("下载oss文件报错:" + e.getMessage() + ", fileId=" + fileId, e); } } public void setAccessKey(String accessKey) { this.accessKey = accessKey; } public void setSecretKey(String secretKey) { this.secretKey = secretKey; } public void setEndpoint(String endpoint) { this.endpoint = endpoint; } public void setBucketName(String bucketName) { this.bucketName = bucketName; } public void setProtocol(Protocol protocol) { this.protocol = protocol; } private String bucketName = "ctoms-file"; public String endpoint = "http://10.2.36.9:8080"; private String accessKey = "4XJOR8RXEWWRVV8N4HOC"; private String secretKey = "1Dp2ua3lcCocEQJMf1VtHBABPfpkUxF4gGE3xacW"; private Protocol protocol = Protocol.HTTP; // private AmazonS3 amazonS3Client; public String createFileOssPath(String fileId, String ext) { Calendar ca = Calendar.getInstance(); String year = ca.get(Calendar.YEAR) + ""; String mon = ca.get(Calendar.MONTH) + 1 + ""; String day = ca.get(Calendar.DAY_OF_MONTH) + ""; String directory = year + "/" + mon + "/" + day + "/"; // mkdirFolder(directory); return fileId + StringUtils.SYMBOL_DOT + ext; } // 上传前上设置文件夹 public boolean mkdirFolder(String directory) { AmazonS3 client = this.acquireOneClient(); PutObjectResult putObjectResult = client.putObject(bucketName, directory, new ByteArrayInputStream(new byte[0]), null); return putObjectResult != null; } }