From b011d9e0d056d01d3f9b77dd52cda08b0a776a3a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B0=91=E5=B9=B4=E6=A2=A6=E4=B8=8E=E7=A0=96?= <2847127106@qq.com> Date: Mon, 9 Sep 2024 16:38:34 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9Eoss=E5=B7=A5=E5=85=B7?= =?UTF-8?q?=E7=B1=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/muyu/common/core/utils/OssUtil.java | 275 ++++++++++++++++++ 1 file changed, 275 insertions(+) create mode 100644 src/main/java/com/muyu/common/core/utils/OssUtil.java diff --git a/src/main/java/com/muyu/common/core/utils/OssUtil.java b/src/main/java/com/muyu/common/core/utils/OssUtil.java new file mode 100644 index 0000000..e10c59e --- /dev/null +++ b/src/main/java/com/muyu/common/core/utils/OssUtil.java @@ -0,0 +1,275 @@ +package com.muyu.common.core.utils; + + +import com.aliyun.oss.OSS; +import com.aliyun.oss.OSSClientBuilder; +import com.aliyun.oss.OSSException; +import com.aliyun.oss.common.auth.CredentialsProviderFactory; +import com.aliyun.oss.common.auth.EnvironmentVariableCredentialsProvider; +import com.aliyun.oss.common.utils.BinaryUtil; +import com.aliyun.oss.model.*; +import com.aliyuncs.exceptions.ClientException; +import lombok.extern.log4j.Log4j2; +import org.springframework.web.multipart.MultipartFile; + +import java.io.*; +import java.text.SimpleDateFormat; +import java.time.LocalDateTime; +import java.util.Date; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.UUID; + +/** + * @Description Oss工具 + */ +@Log4j2 +public class OssUtil { + + /** + * Endpoint 存储对象概述 阿里云主账号AccessKey,accessKeySecret拥有所有API的访问权限 访问路径前缀 存储对象概述 + */ + private static String endPoint = "oss-cn-shanghai.aliyuncs.com"; + private static String accessKeyId = "LTAI5tN9vdDeBioiVbGG3UG3"; + private static String accessKeySecret = "gzhfYLb0UX0zH35DOki9yi1Q35ndgS"; + // 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。 + private static EnvironmentVariableCredentialsProvider credentialsProvider; + + private static final Integer OSS_TASK_NUM = 5; + /** + * 取值范围为100 KB~5 GB。默认值为100 KB + */ + private static final Integer OSS_PART_SIZE = 1024 * 1024; //1MB + /** + * 开启断点续传 + */ + private static final Boolean OSS_ENABLE_CHECKPOINT = true; + + /** + * bucket名称 + * + * @return + */ + private static String bucketName = "wangxin-123"; + + private static String accessPre = "https://"+bucketName+"."+endPoint+"/"; + + private static OSS ossClient; + + static { + try { + credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider(); + } catch (ClientException e) { + throw new RuntimeException(e); + } + ossClient = new OSSClientBuilder().build( + endPoint, + accessKeyId, + accessKeySecret); + log.info("oss服务连接成功!"); + } + + /** + * 默认路径上传本地文件 + * + * @param filePath + */ + public static String uploadFile(String filePath) { + return uploadFileForBucket(bucketName, getOssFilePath(filePath), filePath); + } + + /** + * 默认路径上传multipartFile文件 + * + * @param multipartFile + */ + public static String uploadMultipartFile(MultipartFile multipartFile) throws IOException { + return uploadMultipartFile(bucketName, getOssFilePath(multipartFile.getOriginalFilename()), multipartFile); + } + + /** + * 上传 multipartFile 类型文件 + * + * @param bucketName + * @param ossPath + * @param multipartFile + */ + public static String uploadMultipartFile(String bucketName, String ossPath, MultipartFile multipartFile) throws IOException { + InputStream inputStream = null; + try { + inputStream = multipartFile.getInputStream(); + uploadFileInputStreamForBucket(bucketName, ossPath, inputStream); + } catch (IOException e) { + e.printStackTrace(); + }finally { + if (null != inputStream) { + inputStream.close(); + } + } + return accessPre + ossPath; + } + + /** + * 使用File上传PutObject上传文件 ** 程序默认使用次方法上传 + * + * @param bucketName 实例名称 + * @param ossPath oss存储路径 + * @param filePath 本地文件路径 + * @return 文件路径 + */ + public static String uploadFileForBucket(String bucketName, String ossPath, String filePath) { + // 创建PutObjectRequest对象。 + PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, ossPath, new File(filePath)); + // 上传 + ossClient.putObject(putObjectRequest); + return accessPre + ossPath; + } + + /** + * 使用文件流上传到指定的bucket实例 + * + * @param bucketName 实例名称 + * @param ossPath oss存储路径 + * @param filePath 本地文件路径 + */ + public static String uploadFileInputStreamForBucket(String bucketName, String ossPath, String filePath) { + + // 填写本地文件的完整路径。如果未指定本地路径,则默认从示例程序所属项目对应本地路径中上传文件流。 + InputStream inputStream = null; + try { + inputStream = new FileInputStream(filePath); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } + // 填写Bucket名称和Object完整路径。Object完整路径中不能包含Bucket名称。 + uploadFileInputStreamForBucket(bucketName, ossPath, inputStream); + //断点续传 + uploadFileBreakpointResume(bucketName, ossPath, filePath); + return accessPre + ossPath; + } + + public static void uploadFileInputStreamForBucket(String bucketName, String ossPath, InputStream inputStream) { + ossClient.putObject(bucketName, ossPath, inputStream); + } + + public static void uploadFileBreakpointResume(String bucketName, String ossPath, String filePath) { + try { + // 通过UploadFileRequest设置多个参数。 + // 依次填写Bucket名称(例如examplebucket)以及Object完整路径(例如exampledir/exampleobject.txt),Object完整路径中不能包含Bucket名称。 + UploadFileRequest uploadFileRequest = new UploadFileRequest(bucketName, ossPath); + // 通过UploadFileRequest设置单个参数。 + // 填写本地文件的完整路径,例如D:\\localpath\\examplefile.txt。如果未指定本地路径,则默认从示例程序所属项目对应本地路径中上传文件。 + uploadFileRequest.setUploadFile(filePath); + // 指定上传并发线程数,默认值为1。 + uploadFileRequest.setTaskNum(OSS_TASK_NUM); + // 指定上传的分片大小,单位为字节,取值范围为100 KB~5 GB。默认值为100 KB。 + uploadFileRequest.setPartSize(OSS_PART_SIZE); + // 开启断点续传,默认关闭。 + uploadFileRequest.setEnableCheckpoint(OSS_ENABLE_CHECKPOINT); + // 记录本地分片上传结果的文件。上传过程中的进度信息会保存在该文件中,如果某一分片上传失败,再次上传时会根据文件中记录的点继续上传。上传完成后,该文件会被删除。 + // 如果未设置该值,默认与待上传的本地文件同路径,名称为${uploadFile}.ucp。 + //uploadFileRequest.setCheckpointFile(); + // 设置上传回调,参数为Callback类型。 + //uploadFileRequest.setCallback("yourCallbackEvent"); + + // 断点续传上传。 + ossClient.uploadFile(uploadFileRequest); + } catch (OSSException oe) { + System.out.println("Caught an OSSException, which means your request made it to OSS, " + + "but was rejected with an error response for some reason."); + System.out.println("Error Message:" + oe.getErrorMessage()); + System.out.println("Error Code:" + oe.getErrorCode()); + System.out.println("Request ID:" + oe.getRequestId()); + System.out.println("Host ID:" + oe.getHostId()); + } catch (Throwable ce) { + System.out.println("Caught an ClientException, which means the client encountered " + + "a serious internal problem while trying to communicate with OSS, " + + "such as not being able to access the network."); + System.out.println("Error Message:" + ce.getMessage()); + } finally { + // 关闭OSSClient。 + if (ossClient != null) { + ossClient.shutdown(); + } + } + } + + /** + * 下载 + * + * @param ossFilePath + * @param filePath + */ + public static void downloadFile(String ossFilePath, String filePath) { + downloadFileForBucket(bucketName, ossFilePath, filePath); + } + + /** + * 下载 + * + * @param bucketName 实例名称 + * @param ossFilePath oss存储路径 + * @param filePath 本地文件路径 + */ + public static void downloadFileForBucket(String bucketName, String ossFilePath, String filePath) { + ossClient.getObject(new GetObjectRequest(bucketName, ossFilePath), new File(filePath)); + } + + /** + * @return + */ + public static String getOssDefaultPath() { + LocalDateTime now = LocalDateTime.now(); + String url = + now.getYear() + "/" + + now.getMonth() + "/" + + now.getDayOfMonth() + "/" + + now.getHour() + "/" + + now.getMinute() + "/"; + return url; + } + + public static String getOssFilePath(String filePath) { + String fileSuf = filePath.substring(filePath.indexOf(".") + 1); + return getOssDefaultPath() + UUID.randomUUID().toString() + "." + fileSuf; + } + + + public static Map getUrl() throws ClientException { + + // 设置上传到OSS文件的前缀,可置空此项。置空后,文件将上传至Bucket的根目录下。 + String date = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()); + String dir = "uploadTest/"+date+"/"; + OSS ossClient = new OSSClientBuilder().build(endPoint, credentialsProvider); + try { + long expireTime = 30; + long expireEndTime = System.currentTimeMillis() + expireTime * 1000; + Date expiration = new Date(expireEndTime); + // PostObject请求最大可支持的文件大小为5 GB,即CONTENT_LENGTH_RANGE为5*1024*1024*1024。 + PolicyConditions policyConds = new PolicyConditions(); + policyConds.addConditionItem(PolicyConditions.COND_CONTENT_LENGTH_RANGE, 0, 1048576000); + policyConds.addConditionItem(MatchMode.StartWith, PolicyConditions.COND_KEY, dir); + + String postPolicy = ossClient.generatePostPolicy(expiration, policyConds); + byte[] binaryData = postPolicy.getBytes("utf-8"); + String accessId = credentialsProvider.getCredentials().getAccessKeyId(); + String encodedPolicy = BinaryUtil.toBase64String(binaryData); + String postSignature = ossClient.calculatePostSignature(postPolicy); + + Map respMap = new LinkedHashMap(); + respMap.put("accessId", accessId); + respMap.put("policy", encodedPolicy); + respMap.put("signature", postSignature); + respMap.put("dir", dir); + respMap.put("host", accessPre); + respMap.put("expire", String.valueOf(expireEndTime / 1000)); + // respMap.put("expire", formatISO8601Date(expiration)); + return respMap; + } catch (Exception e) { + throw new ClientException("【上传文件失败】:返回前端所需参数异常;【原因】:{}",e.getMessage()); + } finally { + ossClient.shutdown(); + } + } + +}