package edu.travel.upload.obs; import com.obs.services.ObsClient; import com.obs.services.exception.ObsException; import com.obs.services.internal.ServiceException; import com.obs.services.model.*; import edu.travel.upload.obs.property.ObsProperties; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.stereotype.Component; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.Base64; import java.util.Optional; @Component @ConditionalOnClass(ObsClient.class) public class HuaweiOBSUtils { Logger log = LoggerFactory.getLogger(HuaweiOBSUtils.class); @Autowired private ObsClient obsClient; @Autowired private ObsProperties obsProperties; //注意这里传进来的参数是处理后的图片 base64 参数,处理方法只需要调用 api,这里不做过多解释,可以上网查询转换方法,另外是指定的文件名称和bucket名称,上传后的文件将是以该 fileName 存在于该bucket 内 //此方法是用于上传文件,内部调用了 obs 的含有 MD5 参数校验的api方法 public void uploadPic(String base64, String fileName) { byte[] bytes = Base64.getDecoder().decode(base64); ObjectMetadata meta = new ObjectMetadata(); // 设置MD5校验。 String md5 = toBase64String(calculateMd5(bytes)); meta.setContentMd5(md5); try (InputStream inputStream = new ByteArrayInputStream(bytes)) { PutObjectResult result = obsClient.putObject(obsProperties.getBucketName(), fileName, inputStream,meta); } catch (Exception e) { log.error("Upload failed: ", e); } } // 计算 MD5 值的方法 private static byte[] calculateMd5(byte[] data) { try { MessageDigest md = MessageDigest.getInstance("MD5"); return md.digest(data); } catch (NoSuchAlgorithmException e) { throw new RuntimeException("MD5 algorithm not found.", e); } } // 将字节数组转换为 Base64 编码的字符串 private static String toBase64String(byte[] bytes) { return Base64.getEncoder().encodeToString(bytes); } //该方法是用于检查bucket 内是否有指定文件,内部调用了 obs 的获取文件方法 public Boolean checkExist(String fileName,String bucketName) { ObsObject object = null; InputStream inputStream = null; try { object = obsClient.getObject(bucketName, fileName); inputStream = object.getObjectContent(); if (inputStream != null) { return true; } } catch (Exception e) { log.error("请求异常:{}", fileName, e); return false; } finally { // 确保关闭 InputStream try { if (inputStream != null) { inputStream.close(); } } catch (IOException e) { log.error("关闭 InputStream 异常", e); } } return false; } //该方法是用于获取指定时间内的文件下载链接 public String getPicViewUrlByInternal(String fileName) { Boolean aBoolean = checkExist(fileName,obsProperties.getBucketName()); if (!aBoolean) { return null; } // 生成以GET方法访问的签名URL,访客可以直接通过浏览器访问相关内容。 String url = generatePresignedUrl(obsProperties.getExpiration(), fileName,obsProperties.getBucketName()); return url; } private String generatePresignedUrl(Long expire,String fileName,String bucketName) { TemporarySignatureResponse response = null; try { // URL有效期,3600秒 //long expireSeconds = 3600L; TemporarySignatureRequest request = new TemporarySignatureRequest(HttpMethodEnum.GET, expire); request.setBucketName(bucketName); request.setObjectKey(fileName); response = obsClient.createTemporarySignature(request); } catch (ObsException e) { log.error("get obs failed :{}", e.getMessage()); throw new ServiceException(e.getMessage()); } return Optional.ofNullable(response) .map(TemporarySignatureResponse::getSignedUrl) .orElse(null); } }