package com.cku.thirdparty.oss; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.Calendar; import java.util.Date; import java.util.Locale; import java.util.Objects; import java.util.UUID; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Configuration; import org.springframework.web.multipart.MultipartFile; import com.aliyun.oss.OSSClient; import com.aliyun.oss.common.utils.BinaryUtil; import com.aliyun.oss.model.CannedAccessControlList; import com.aliyun.oss.model.GetObjectRequest; import com.aliyun.oss.model.MatchMode; import com.aliyun.oss.model.OSSObject; import com.aliyun.oss.model.PolicyConditions; import lombok.extern.slf4j.Slf4j; @Slf4j @Configuration public class OssApiClient { public static final String ALI_OSS = "ali_oss"; private static final String PATH = "/"; public static final String HTTPS = "https://"; @Autowired private OSSClient ossClient; @Value("${aliyun.oss.accessKeyId}") private String accessKeyId; @Value("${aliyun.oss.bucketName}") private String bucketName; @Value("${aliyun.oss.projectName}") private String projectName; /** * 文件上传:根据module、年、月组成路径,生成新的唯一文件名,存储文件 * * @param file 待上传文件 * @param module 文件所属模块 example member,userUpload,banner * @return 上传文件结果 */ public OssUploadResult upload(MultipartFile file, String module) { InputStream is = null; try { // 获取上传文件流 is = file.getInputStream(); String originalName = file.getOriginalFilename(); // 文件上传至阿里云 OssUploadResult result = this.upload(is, module, originalName); return result; } catch (IOException e) { log.error(e.getMessage()); } finally { if (Objects.nonNull(is)) { try { is.close(); } catch (IOException e) { e.printStackTrace(); } } } return null; } /** * 文件上传:根据module、年、月组成路径,生成新的唯一文件名,存储文件 * * @param fileDir 待上传文件的路径 * @param module 文件所属模块 example member,userUpload,banner * @param delFile 上传完毕后,是否删除已上传文件 true 为删除 * @return 上传文件结果 */ public OssUploadResult upload(String fileDir, String module, boolean delFile) { FileInputStream fis = null; try { File file = new File(fileDir); fis = new FileInputStream(file); OssUploadResult result = this.upload(fis, module, file.getName()); if (delFile && file.exists()) { file.delete(); } return result; } catch (Exception e) { log.error(e.getMessage()); } finally { if (Objects.nonNull(fis)) { try { fis.close(); } catch (IOException e) { e.printStackTrace(); } } } return null; } /** * 文件覆盖:用新文件覆盖原有OSS文件 * * @param fileDir 待上传文件的路径 * @param filePath OSS上文件存储的路径 * @param fileName OSS上文件名称 * @param delFile 上传完毕后,是否删除已上传文件 true 为删除 */ public void uploadCover(String fileDir, String objectPath, String objectName, boolean delFile) { FileInputStream fis = null; try { File file = new File(fileDir); fis = new FileInputStream(file); // 文件上传至阿里云 ossClient.putObject(bucketName, objectPath + PATH + objectName, fis); if (delFile && file.exists()) { file.delete(); } } catch (Exception e) { log.error(e.getMessage()); } finally { if (Objects.nonNull(fis)) { try { fis.close(); } catch (IOException e) { e.printStackTrace(); } } } } /** * 公用上传方法 * * @param is 待上传文件的输入流 * @param module 文件所属模块 * @param originalName 原文件名称 * @return 文件上传结果 */ public OssUploadResult upload(InputStream is, String module, String originalName) { log.info("================上传OSS开始==================="); if (!ossClient.doesBucketExist(bucketName)) { log.info("================" + bucketName + "不存在,创建Bucket==================="); // 创建bucket ossClient.createBucket(bucketName); // 设置oss实例的访问权限:公共读 ossClient.setBucketAcl(bucketName, CannedAccessControlList.PublicRead); } // 构建日期路径:avatar/2019/2/26/文件名 String filePath = this.getExtensionPath(module); String newFileName = UUID.randomUUID().toString().replaceAll("-", "") + getExtension(originalName); // 文件上传至阿里云 ossClient.putObject(bucketName, filePath + PATH + newFileName, is); // 获取url地址 String uploadUrl = this.getOssUrl(filePath, newFileName); log.info("================上传OSS结束,文件地址:" + filePath + "==================="); return OssUploadResult.builder().extensionPath(filePath).originalName(originalName).objectName(newFileName) .uploadUrl(uploadUrl).build(); } /** * 公用上传方法 * * @param is 待上传文件的输入流 * @param module 文件所属模块 * @param originalName 原文件名称 * @return 文件上传结果 */ public OssUploadResult uploadTmp(InputStream is, String module, String originalName) { log.info("================上传OSS开始==================="); if (!ossClient.doesBucketExist(bucketName)) { log.info("================" + bucketName + "不存在,创建Bucket==================="); // 创建bucket ossClient.createBucket(bucketName); // 设置oss实例的访问权限:公共读 ossClient.setBucketAcl(bucketName, CannedAccessControlList.PublicRead); } // 构建日期路径:avatar/2019/2/26/文件名 String filePath = this.getExtensionPath(module); // 文件上传至阿里云 ossClient.putObject(bucketName, filePath + PATH + originalName, is); // 获取url地址 String uploadUrl = this.getOssUrl(filePath, originalName); log.info("================上传OSS结束,文件地址:" + filePath + "==================="); return OssUploadResult.builder().extensionPath(filePath).originalName(originalName).objectName(originalName) .uploadUrl(uploadUrl).build(); } /** * 根据模块获取文件存储路径(module、年、月组成路径) * * @param module 所属模块 * @return 存储路径 */ private String getExtensionPath(String module) { Calendar calendar = Calendar.getInstance(Locale.getDefault()); String path = projectName + PATH + module + PATH + calendar.get(Calendar.YEAR) + PATH + (calendar.get(Calendar.MONTH) + 1); return path; } /** * OSS文件下载到特定目录下 * * @param objectPath 文件在OSS中放置的相对位置,为不包含Bucket名称在内的Object完整路径,例如/member/2022/1 * @param objectName 文件在OSS中文件名 * @param filePath 下载文件存储本地磁盘的路径 */ public void fileDownload(String objectPath, String objectName, String filePath) { try { ossClient.getObject(new GetObjectRequest(bucketName, objectPath + PATH + objectName), new File(filePath)); } catch (Exception e) { log.error(e.getMessage()); } } /** * @param objectPath 文件在OSS中放置的相对位置,为不包含Bucket名称在内的Object完整路径,例如/member/2022/1 * @param objectName 文件在OSS中文件名 * @param out 下载后的文件,转换成的输出流 */ public void fileDownload(String objectPath, String objectName, OutputStream out) { OSSObject ossObject = null; try { log.info("======aliyun.oss.bucketName======" + bucketName); ossObject = ossClient.getObject(bucketName, objectPath + PATH + objectName); InputStream is = ossObject.getObjectContent(); int read; byte b[] = new byte[1024 * 1024]; read = is.read(b); while (read != -1) { out.write(b, 0, read); read = is.read(b); } } catch (Exception e) { log.error(e.getMessage()); } finally { if (Objects.nonNull(ossObject)) { try { ossObject.close(); } catch (IOException e) { e.printStackTrace(); } } } } /** * 删除存放在OSS服务器中的文件 * * @param objectPath 文件在OSS中放置的相对位置,为不包含Bucket名称在内的Object完整路径,例如/member/2022/1 * @param objectName 文件在OSS中文件名 */ public void fileDelete(String objectPath, String objectName) { // 删除文件或目录。如果要删除目录,目录必须为空。 ossClient.deleteObject(bucketName, objectPath + PATH + objectName); } /** * 获取OSS文件访问地址 * * @param objectPath 文件在OSS中放置的相对位置,为不包含Bucket名称在内的Object完整路径,例如/member/2022/1 * @param objectName 文件在OSS中文件名 * @return */ public String getOssUrl(String objectPath, String objectName) { // 获取url地址 return HTTPS + bucketName + "." + ossClient.getEndpoint().getHost() + PATH + objectPath + PATH + objectName; } /** * 获取文件后缀名 * * @param originalName 文件原名称 * @return */ public String getExtension(String originalName) { char ch; int len; if (Objects.isNull(originalName) || (len = originalName.length()) == 0 || (ch = originalName.charAt(len - 1)) == '/' || ch == '\\' || ch == '.') return ""; int dotInd = originalName.lastIndexOf('.'); int sepInd = Math.max(originalName.lastIndexOf('/'), originalName.lastIndexOf('\\')); if (dotInd <= sepInd) { return ""; } else { return originalName.substring(dotInd).toLowerCase(); } } public OssSignatureResult getSignature(String module, String fileName) { try { long expireTime = 30; long expireEndTime = System.currentTimeMillis() + expireTime * 1000; Date expiration = new Date(expireEndTime); // 构建日期路径:avatar/2019/2/26/文件名 String filePath = this.getExtensionPath(module); String newFileName = filePath + PATH + UUID.randomUUID().toString().replaceAll("-", "") + getExtension(fileName); PolicyConditions policyConds = new PolicyConditions(); policyConds.addConditionItem(PolicyConditions.COND_CONTENT_LENGTH_RANGE, 0, 1048576000); policyConds.addConditionItem(MatchMode.StartWith, PolicyConditions.COND_KEY, newFileName); String postPolicy = ossClient.generatePostPolicy(expiration, policyConds); byte[] binaryData = postPolicy.getBytes("utf-8"); String encodedPolicy = BinaryUtil.toBase64String(binaryData); String postSignature = ossClient.calculatePostSignature(postPolicy); return OssSignatureResult.builder().accessid(accessKeyId).policy(encodedPolicy).signature(postSignature) .dir(newFileName).host(HTTPS + bucketName + "." + ossClient.getEndpoint().getHost()) .expire(String.valueOf(expireEndTime / 1000)).build(); } catch (Exception e) { e.printStackTrace(); } return null; } }