package com.gxwebsoft.common.system.controller; import cn.hutool.core.util.StrUtil; import com.alibaba.fastjson.JSONObject; import com.aliyun.oss.ClientException; import com.aliyun.oss.OSS; import com.aliyun.oss.OSSClientBuilder; import com.aliyun.oss.OSSException; import com.aliyun.oss.common.auth.CredentialsProvider; import com.aliyun.oss.common.auth.DefaultCredentialProvider; import com.aliyun.oss.common.utils.BinaryUtil; import com.aliyun.oss.model.PolicyConditions; import com.aliyun.oss.model.PutObjectRequest; import com.aliyun.oss.model.PutObjectResult; import com.aliyuncs.DefaultAcsClient; import com.aliyuncs.auth.sts.AssumeRoleRequest; import com.aliyuncs.auth.sts.AssumeRoleResponse; import com.aliyuncs.http.MethodType; import com.aliyuncs.profile.DefaultProfile; import com.aliyuncs.profile.IClientProfile; import com.gxwebsoft.common.core.annotation.OperationLog; import com.gxwebsoft.common.core.config.ConfigProperties; import com.gxwebsoft.common.core.utils.FileServerUtil; import com.gxwebsoft.common.core.utils.RedisUtil; import com.gxwebsoft.common.core.web.ApiResult; import com.gxwebsoft.common.core.web.BaseController; import com.gxwebsoft.common.system.entity.Company; import com.gxwebsoft.common.system.entity.FileRecord; import com.gxwebsoft.common.system.service.CompanyService; import com.gxwebsoft.common.system.service.FileRecordService; import com.gxwebsoft.common.system.service.SettingService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import java.io.File; import java.nio.charset.StandardCharsets; import java.text.SimpleDateFormat; import java.util.Date; import java.util.HashMap; import java.util.Map; /** * 阿里云OSS云存储 * * @author WebSoft * @since 2022-11-19 13:54:27 */ @Api(tags = "阿里云OSS云存储") @RestController @RequestMapping("/api/oss") public class AliOssController extends BaseController { @Resource private ConfigProperties config; @Resource private RedisUtil redisUtil; @Resource private FileRecordService fileRecordService; @Resource private CompanyService companyService; @Resource private SettingService settingService; @ApiOperation("上传文件") @PostMapping("/upload") public ApiResult upload(@RequestParam MultipartFile file, HttpServletRequest request) throws Exception{ // 获取租户ID String tenantId = request.getHeader("TenantId"); String companyId = request.getHeader("CompanyId"); String groupId = request.getHeader("GroupId"); String appId = request.getHeader("AppId"); if(StrUtil.isBlank(tenantId)){ return fail("传参错误",null); } // 读取配置信息 JSONObject settingInfo; String key3 = "Upload:" + tenantId; settingInfo = redisUtil.get(key3, JSONObject.class); if (settingInfo == null) { settingInfo = settingService.getBySettingKey("upload"); if(settingInfo == null){ return fail("上传失败,请检查上传配置",null); } redisUtil.set(key3,settingInfo); } String endpoint = settingInfo.getString("bucketEndpoint"); String bucketDomain = settingInfo.getString("bucketDomain"); String bucketName = settingInfo.getString("bucketName"); String accessKeyId = settingInfo.getString("accessKeyId"); String accessKeySecret = settingInfo.getString("accessKeySecret"); // 判断是否登录 String authorization = getAuthorization(); // 判断存储空间是否已满 String key = "StorageIsFull:" + tenantId; String storageIsFull = redisUtil.get(key); if(StrUtil.isNotBlank(storageIsFull)){ // 使用自定义云存储不限制 if(bucketName.equals("oss-gxwebsoft")){ return fail("存储空间已满", null); } } // 上传文件结果 FileRecord result; CredentialsProvider credentialsProvider = new DefaultCredentialProvider(accessKeyId, accessKeySecret); // 创建OSSClient实例。 OSS ossClient = new OSSClientBuilder().build(endpoint, credentialsProvider); try { String dir = getUploadDir(); File upload = FileServerUtil.upload(file, dir, config.getUploadUuidName()); String path = upload.getAbsolutePath().replace("\\", "/").substring(dir.length()); String originalName = file.getOriginalFilename(); // 创建PutObjectRequest对象。 PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, path, upload); // 如果需要上传时设置存储类型和访问权限,请参考以下示例代码。 // ObjectMetadata metadata = new ObjectMetadata(); // metadata.setHeader(OSSHeaders.OSS_STORAGE_CLASS, StorageClass.Standard.toString()); // metadata.setObjectAcl(CannedAccessControlList.Private); // putObjectRequest.setMetadata(metadata); // 上传文件。 PutObjectResult ossResult = ossClient.putObject(putObjectRequest); // 保存记录并返回 result = new FileRecord(); if(StrUtil.isNotBlank(authorization)){ result.setCreateUserId(getLoginUserId()); } if(StrUtil.isNotBlank(companyId)){ result.setCompanyId(Integer.valueOf(companyId)); } if(StrUtil.isNotBlank(groupId)){ result.setGroupId(Integer.valueOf(groupId)); } if(StrUtil.isNotBlank(appId)){ result.setAppId(Integer.valueOf(appId)); } path = "/".concat(path); result.setName(StrUtil.isBlank(originalName) ? upload.getName() : originalName); result.setLength(upload.length()); result.setPath(bucketDomain + path); result.setThumbnail(bucketDomain + path + "?x-oss-process=image/resize,m_fixed,w_100,h_100/quality,Q_90"); result.setUrl(bucketDomain + path + "?x-oss-process=image/resize,w_750/quality,Q_90"); result.setDownloadUrl(bucketDomain + path); String contentType = FileServerUtil.getContentType(upload); result.setContentType(contentType); result.setTenantId(Integer.valueOf(tenantId)); upload.delete(); fileRecordService.save(result); // 更新存储空间 if(companyId != null){ Company company = companyService.getById(Integer.valueOf(companyId)); company.setStorage(company.getStorage() + result.getLength()); if(company.getStorage().compareTo(company.getStorageMax()) > 0){ redisUtil.set(key,1); } companyService.updateById(company); } return success(result); } 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 (ClientException 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 { if (ossClient != null) { ossClient.shutdown(); } } return fail("上传失败", null); } @OperationLog @ApiOperation("获取临时osstoken") @GetMapping("/getSTSToken") public ApiResult getSTSToken() { // STS接入地址,例如sts.cn-hangzhou.aliyuncs.com。 String endpoint = "sts.cn-shenzhen.aliyuncs.com"; // 填写步骤1生成的RAM用户访问密钥AccessKey ID和AccessKey Secret。 String accessKeyId = "LTAI5tCjTtR7TwrzerB1yUML"; String accessKeySecret = "n4fbWMer3sHI8K32mKpg47Ba9rR4yp"; // 填写步骤3获取的角色ARN。 String roleArn = "acs:ram::1470199532233684:role/wsoss"; // 自定义角色会话名称,用来区分不同的令牌,例如可填写为SessionTest。 String roleSessionName = "wsoss"; // 设置临时访问凭证的有效时间为3600秒。 Long durationSeconds = 3600L; try { // regionId表示RAM的地域ID。以华东1(杭州)地域为例,regionID填写为cn-hangzhou。也可以保留默认值,默认值为空字符串("")。 String regionId = ""; // 添加endpoint。适用于Java SDK 3.12.0及以上版本。 DefaultProfile.addEndpoint(regionId, "Sts", endpoint); // 构造default profile。 IClientProfile profile = DefaultProfile.getProfile(regionId, accessKeyId, accessKeySecret); // 构造client。 DefaultAcsClient client = new DefaultAcsClient(profile); final AssumeRoleRequest request = new AssumeRoleRequest(); // 适用于Java SDK 3.12.0及以上版本。 request.setSysMethod(MethodType.POST); // 适用于Java SDK 3.12.0以下版本。 //request.setMethod(MethodType.POST); request.setRoleArn(roleArn); request.setRoleSessionName(roleSessionName); // request.setPolicy(policy); request.setDurationSeconds(durationSeconds); final AssumeRoleResponse response = client.getAcsResponse(request); return success(response); } catch (ClientException | com.aliyuncs.exceptions.ClientException e) { System.out.println("Failed:"); System.out.println("Error message: " + e.getMessage()); return fail(e.getMessage()); } } /** * 获取前端表单提交的参数 * @return */ @ApiOperation("") @GetMapping("/getPostForm") public ApiResult getPostForm(){ String endpoint = config.getEndpoint(); // RAM用户的访问密钥(AccessKey ID和AccessKey Secret)。 String accessKeyId = "LTAI5t8UTh8CTXEi2dYxobhj"; String accessKeySecret = "fNdJOT4KAjrVrzHNAcSJuUCy9ZljD9"; // 使用代码嵌入的RAM用户的访问密钥配置访问凭证。 CredentialsProvider credentialsProvider = new DefaultCredentialProvider(accessKeyId, accessKeySecret); // 填写Bucket名称,例如examplebucket。 String bucket = config.getBucketName(); OSS ossClient = new OSSClientBuilder().build(endpoint, credentialsProvider); try { String host = "https://" + bucket + "." + endpoint; String format = new SimpleDateFormat("yyyy-MM-dd").format(new Date()); long expireTime = 60; long expireEndTime = System.currentTimeMillis() + expireTime * 1000; Date expiration = new Date(expireEndTime); PolicyConditions policyConds = new PolicyConditions(); policyConds.addConditionItem(PolicyConditions.COND_CONTENT_LENGTH_RANGE,0,100*1024*1024); String postPolicy = ossClient.generatePostPolicy(expiration, policyConds); byte[] binaryData = postPolicy.getBytes(StandardCharsets.UTF_8); String encodedPolicy = BinaryUtil.toBase64String(binaryData); String postSignature = ossClient.calculatePostSignature(postPolicy); Map result = new HashMap<>(); result.put("polocyBase64",encodedPolicy); result.put("signature",postSignature); result.put("expireEndTime",expireEndTime); return success(result); } finally { ossClient.shutdown(); } } /** * 文件上传位置(服务器) */ private String getUploadDir() { return config.getUploadPath() + "file/"; } }