Ks3文件上传,删除,刷新CDN缓存

1.准备项目环境,搭建springboot工程
2.调整maven的pom.xml,导入ks3相关jar包,依赖如下

 <dependency> <groupId>com.ksyun</groupId> <artifactId>ks3-kss-java-sdk</artifactId> <version>0.8.11</version> </dependency> <!-- 模拟请求 --> <dependency> <groupId>com.mashape.unirest</groupId> <artifactId>unirest-java</artifactId> <version>1.4.9</version> </dependency> 

3.代码实现

application.xml

Ks3 config

ks3:
accessKey: XXXX
secretKey: XXXX
endPoint: ks3-cn-beijing.ksyun.com
bucketName: xxxxx
host: xxxxxx

package com.xy.quickapp.aidiscern.util;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.*;

/**

  • @author: kang.zou

  • @date:2019/8/7

  • AWS V4 签名处理工具

  • 参考链接:https://docs.aws.amazon.com/zh_cn/general/latest/gr/sigv4_signing.html
    */
    public class AWSAuth {
    private AWSAuth() {
    }

    public static class Builder {

     private String accessKeyID; private String secretAccessKey; private String regionName; private String serviceName; private String httpMethodName; private String canonicalURI; private TreeMap<String, String> queryParametes; private TreeMap<String, String> awsHeaders; private String payload; private boolean debug = false; public Builder(String accessKeyID, String secretAccessKey) { this.accessKeyID = accessKeyID; this.secretAccessKey = secretAccessKey; } public Builder regionName(String regionName) { this.regionName = regionName; return this; } public Builder serviceName(String serviceName) { this.serviceName = serviceName; return this; } public Builder httpMethodName(String httpMethodName) { this.httpMethodName = httpMethodName; return this; } public Builder canonicalURI(String canonicalURI) { this.canonicalURI = canonicalURI; return this; } public Builder queryParametes(TreeMap<String, String> queryParametes) { this.queryParametes = queryParametes; return this; } public Builder awsHeaders(TreeMap<String, String> awsHeaders) { this.awsHeaders = awsHeaders; return this; } public Builder payload(String payload) { this.payload = payload; return this; } public Builder debug() { this.debug = true; return this; } public AWSAuth build() { return new AWSAuth(this); } 

    }

    private String accessKeyID;
    private String secretAccessKey;
    private String regionName;
    private String serviceName;
    private String httpMethodName;
    private String canonicalURI;
    private TreeMap<String, String> queryParametes;
    private TreeMap<String, String> awsHeaders;
    private String payload;
    private boolean debug = false;

    /* Other variables */
    private final String HMACAlgorithm = “AWS4-HMAC-SHA256”;
    private final String aws4Request = “aws4_request”;
    private String strSignedHeader;
    private String xAmzDate;
    private String currentDate;

    private AWSAuth(Builder builder) {
    accessKeyID = builder.accessKeyID;
    secretAccessKey = builder.secretAccessKey;
    regionName = builder.regionName;
    serviceName = builder.serviceName;
    httpMethodName = builder.httpMethodName;
    canonicalURI = builder.canonicalURI;
    queryParametes = builder.queryParametes;
    awsHeaders = builder.awsHeaders;
    payload = builder.payload;
    debug = builder.debug;

     /* Get current timestamp value.(UTC) */ xAmzDate = getTimeStamp(); currentDate = getDate(); 

    }

    /**

    • 任务 1:针对签名版本 4 创建规范请求

    • @return
      */
      private String prepareCanonicalRequest() {
      StringBuilder canonicalURL = new StringBuilder("");

      /* Step 1.1 以HTTP方法(GET, PUT, POST, etc.)开头, 然后换行. */
      canonicalURL.append(httpMethodName).append("\n");

      /* Step 1.2 添加URI参数,换行. */
      canonicalURI = canonicalURI == null || canonicalURI.trim().isEmpty() ? “/” : canonicalURI;
      canonicalURL.append(canonicalURI).append("\n");

      /* Step 1.3 添加查询参数,换行. */
      StringBuilder queryString = new StringBuilder("");
      if (queryParametes != null && !queryParametes.isEmpty()) {
      for (Map.Entry<String, String> entrySet : queryParametes.entrySet()) {
      String key = entrySet.getKey();
      String value = entrySet.getValue();
      queryString.append(key).append("=").append(encodeParameter(value)).append("&");
      }

       queryString.deleteCharAt(queryString.lastIndexOf("&")); queryString.append("\n"); 

      } else {
      queryString.append("\n");
      }
      canonicalURL.append(queryString);

      /* Step 1.4 添加headers, 每个header都需要换行. */
      StringBuilder signedHeaders = new StringBuilder("");
      if (awsHeaders != null && !awsHeaders.isEmpty()) {
      for (Map.Entry<String, String> entrySet : awsHeaders.entrySet()) {
      String key = entrySet.getKey();
      String value = entrySet.getValue();
      signedHeaders.append(key).append(";");
      canonicalURL.append(key).append("😊.append(value).append("\n");
      }
      canonicalURL.append("\n");
      } else {
      canonicalURL.append("\n");
      }

      /* Step 1.5 添加签名的headers并换行. */
      strSignedHeader = signedHeaders.substring(0, signedHeaders.length() – 1); // 删掉最后的 “;”
      canonicalURL.append(strSignedHeader).append("\n");

      /* Step 1.6 对HTTP或HTTPS的body进行SHA256处理. */
      payload = payload == null ? “” : payload;
      canonicalURL.append(generateHex(payload));

      return canonicalURL.toString();
      }

    /**

    • 任务 2:创建签名版本 4 的待签字符串

    • @param canonicalURL

    • @return
      */
      private String prepareStringToSign(String canonicalURL) {
      String stringToSign = “”;

      /* Step 2.1 以算法名称开头,并换行. */
      stringToSign = HMACAlgorithm + “\n”;

      /* Step 2.2 添加日期,并换行. */
      stringToSign += xAmzDate + “\n”;

      /* Step 2.3 添加认证范围,并换行. */
      stringToSign += currentDate + “/” + regionName + “/” + serviceName + “/” + aws4Request + “\n”;

      /* Step 2.4 添加任务1返回的规范URL哈希处理结果,然后换行. */
      stringToSign += generateHex(canonicalURL);

      return stringToSign;
      }

    /**

    • 任务 3:为 AWS Signature 版本 4 计算签名

    • @param stringToSign

    • @return
      /
      private String calculateSignature(String stringToSign) {
      try {
      /
      Step 3.1 生成签名的key */
      byte[] signatureKey = getSignatureKey(secretAccessKey, currentDate, regionName, serviceName);

       /* Step 3.2 计算签名. */ byte[] signature = HmacSHA256(signatureKey, stringToSign); /* Step 3.2.1 对签名编码处理 */ String strHexSignature = bytesToHex(signature); return strHexSignature; 

      } catch (Exception ex) {
      ex.printStackTrace();
      }
      return null;
      }

    /**
    *任务 4:将签名信息添加到请求并返回headers
    *

    • @return
      */
      public Map<String, String> getHeaders1() {
      awsHeaders.put(“x-amz-date”, xAmzDate);

      /* 执行任务 1: 创建aws v4签名的规范请求字符串. */
      String canonicalURL = prepareCanonicalRequest();

      /* 执行任务 2: 创建用来认证的字符串 4. */
      String stringToSign = prepareStringToSign(canonicalURL);

      /* 执行任务 3: 计算签名. */
      String signature = calculateSignature(stringToSign);

      if (signature != null) {
      Map<String, String> header = new HashMap<String, String>(0);
      header.put(“x-amz-date”, xAmzDate);
      header.put(“Authorization”, buildAuthorizationString(signature));
      return header;
      } else {
      return null;
      }
      }

    /**

    • 连接前几步处理的字符串生成Authorization header值.
    • @param strSignature
    • @return
      */
      private String buildAuthorizationString(String strSignature) {
      return HMACAlgorithm + " "
      + “Credential=” + accessKeyID + “/” + getDate() + “/” + regionName + “/” + serviceName + “/” + aws4Request + ", "
      + “SignedHeaders=” + strSignedHeader + ", "
      + “Signature=” + strSignature;
      }

    /**

    • 将字符串16进制化.
    • @param data
    • @return
      */
      private String generateHex(String data) {
      MessageDigest messageDigest;
      try {
      messageDigest = MessageDigest.getInstance(“SHA-256”);
      messageDigest.update(data.getBytes(“UTF-8”));
      byte[] digest = messageDigest.digest();
      return String.format("%064x", new java.math.BigInteger(1, digest));
      } catch (NoSuchAlgorithmException | UnsupportedEncodingException e) {
      e.printStackTrace();
      }
      return null;
      }

    /**

    • 以给定的key应用HmacSHA256算法处理数据.
    • @param data
    • @param key
    • @return
    • @throws Exception
    • @reference:
    • http://docs.aws.amazon.com/general/latest/gr/signature-v4-examples.html#signature-v4-examples-java
      */
      private byte[] HmacSHA256(byte[] key, String data) throws Exception {
      String algorithm = “HmacSHA256”;
      Mac mac = Mac.getInstance(algorithm);
      mac.init(new SecretKeySpec(key, algorithm));
      return mac.doFinal(data.getBytes(“UTF-8”));
      }

    /**

    • 生成AWS 签名
    • @param key
    • @param date
    • @param regionName
    • @param serviceName
    • @return
    • @throws Exception
    • @reference
    • http://docs.aws.amazon.com/general/latest/gr/signature-v4-examples.html#signature-v4-examples-java
      */
      private byte[] getSignatureKey(String key, String date, String regionName, String serviceName) throws Exception {
      byte[] kSecret = (“AWS4” + key).getBytes(“UTF8”);
      byte[] kDate = HmacSHA256(kSecret, date);
      byte[] kRegion = HmacSHA256(kDate, regionName);
      byte[] kService = HmacSHA256(kRegion, serviceName);
      byte[] kSigning = HmacSHA256(kService, aws4Request);
      return kSigning;
      }

    final protected static char[] hexArray = “0123456789ABCDEF”.toCharArray();

    /**

    • 将字节数组转换为16进制字符串
    • @param bytes
    • @return
      */
      private String bytesToHex(byte[] bytes) {
      char[] hexChars = new char[bytes.length * 2];
      for (int j = 0; j < bytes.length; j++) {
      int v = bytes[j] & 0xFF;
      hexChars[j * 2] = hexArray[v >>> 4];
      hexChars[j * 2 + 1] = hexArray[v & 0x0F];
      }
      return new String(hexChars).toLowerCase();
      }

    /**

    • 获取yyyyMMdd’T’HHmmss’Z’格式的当前时间
    • @return
      */
      private String getTimeStamp() {
      DateFormat dateFormat = new SimpleDateFormat(“yyyyMMdd’T’HHmmss’Z’”);
      dateFormat.setTimeZone(TimeZone.getTimeZone(“UTC”));//server timezone
      return dateFormat.format(new Date());
      }

    /**

    • 获取yyyyMMdd格式的当前日期
    • @return
      */
      private String getDate() {
      DateFormat dateFormat = new SimpleDateFormat(“yyyyMMdd”);
      dateFormat.setTimeZone(TimeZone.getTimeZone(“UTC”));//server timezone
      return dateFormat.format(new Date());
      }

    /**

    • UTF-8编码
    • @param param
    • @return
      */
      private String encodeParameter(String param){
      try {
      return URLEncoder.encode(param, “UTF-8”);
      } catch (Exception e) {
      return URLEncoder.encode(param);
      }
      }
      }

package com.xy.quickapp.aidiscern.config;

import com.ksyun.ks3.http.HttpClientConfig;
import com.ksyun.ks3.service.Ks3;
import com.ksyun.ks3.service.Ks3Client;
import com.ksyun.ks3.service.Ks3ClientConfig;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**

  • Created by kang.zou

  • on 2020/2/11
    */
    @Configuration
    public class Ks3Config {

    @Value("${ks3.accessKey}")
    private String accessKey;

    @Value("${ks3.secretKey}")
    private String secretKey;

    @Value("${ks3.endPoint}")
    private String endPoint;

    @Value("${ks3.bucketName}")
    private String bucketName;

    @Value("${ks3.host}")
    private String host;

    private String basePath;

    public String getAccessKey() {
    return accessKey;
    }

    public String getSecretKey() {
    return secretKey;
    }

    public String getEndPoint() {
    return endPoint;
    }

    public String getBucketName() {
    return bucketName;
    }

    public String getHost() {
    return host;
    }

    @Bean(name = “ks3Client”)
    public Ks3 ks3Client() {
    Ks3ClientConfig config = new Ks3ClientConfig();

/**

  • 设置服务地址

  • 中国(北京)| ks3-cn-beijing.ksyun.com

  • 中国(上海)| ks3-cn-shanghai.ksyun.com

  • 中国(香港)| ks3-cn-hk-1.ksyun.com

  • 中国(杭州)| kss.ksyun.com

  • 中国(广州)| ks3-cn-guangzhou.ksyun.com

  • 中国(青岛)| ks3-cn-qingdao.ksyun.com

  • 金融专区(北京)| ks3-jr-beijing.ksyun.com

  • 金融专区(上海)| ks3-jr-shanghai.ksyun.com

  • 俄罗斯 | ks3-rus.ksyun.com

  • 新加坡 | ks3-sgp.ksyun.com

  • 如果使用自定义域名,设置endpoint为自定义域名,同时设置domainMode为true

 config.setEndpoint(endPoint); //此处以北京region为例 

/**

*true:表示以自定义域名访问

*false:表示以KS3的外网域名或内网域名访问,默认为false

 config.setDomainMode(false); config.setProtocol(Ks3ClientConfig.PROTOCOL.http); 

/**

*true表示以 endpoint/{bucket}/{key}的方式访问

*false表示以 {bucket}.endpoint/{key}的方式访问

*如果domainMode设置为true,pathStyleAccess可忽略设置

 config.setPathStyleAccess(false); HttpClientConfig hconfig = new HttpClientConfig(); 

//在HttpClientConfig中可以设置httpclient的相关属性,比如代理,超时,重试等。

 config.setHttpClientConfig(hconfig); Ks3 client = new Ks3Client(accessKey,secretKey,config); return client; } 

package com.xy.quickapp.aidiscern.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.ksyun.ks3.dto.CannedAccessControlList;
import com.ksyun.ks3.dto.ObjectMetadata;
import com.ksyun.ks3.service.Ks3;
import com.ksyun.ks3.service.request.PutObjectRequest;
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;
import com.mashape.unirest.http.exceptions.UnirestException;
import com.xy.quickapp.aidiscern.config.Ks3Config;
import com.xy.quickapp.aidiscern.domain.ModelResult;
import com.xy.quickapp.aidiscern.service.Ks3Service;
import com.xy.quickapp.aidiscern.util.AWSAuth;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.InputStream;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;
import java.util.TimeZone;
import java.util.TreeMap;

/**

  • Created by kang.zou

  • on 2020/2/11
    */
    @Service
    public class Ks3ServiceImpl implements Ks3Service {
    private static final Logger log = LoggerFactory.getLogger(Ks3ServiceImpl.class);

    @Autowired
    private Ks3Config ks3Config;

    @Autowired
    private Ks3 ks3Client;

    @Override
    public ModelResult uploadFile(InputStream inputStream, String path, String fileName) {
    JSONObject imgInfo = new JSONObject();
    try {
    ObjectMetadata meta = new ObjectMetadata();
    PutObjectRequest request = new PutObjectRequest(ks3Config.getBucketName(),path, inputStream,meta);
    request.setCannedAcl(CannedAccessControlList.PublicRead);
    ks3Client.putObject(request);
    } catch (Exception e) {
    log.error(“上传异常:{}”, e.getMessage());
    return new ModelResult<>(null).withError(“20001”, “上传文件失败”);
    }
    imgInfo.put(“fileName”, fileName);
    imgInfo.put(“imgUrl”, “https://cdn-qapp.bizport.cn/”+path);
    return new ModelResult<>(imgInfo);
    }

    @Override
    public ModelResult deleteFile(String locationPath) throws UnirestException {
    try {
    ks3Client.deleteObject(ks3Config.getBucketName(), locationPath);
    } catch (Exception e) {
    log.error(“删除异常:{}”, e.getMessage());
    return new ModelResult<>(null).withError(“20001”, “删除文件异常”);
    }
    JSONObject refreshObj = new JSONObject();
    JSONArray files = new JSONArray();
    JSONObject fileObj = new JSONObject();
    fileObj.put(“Url”, “https://cdn-qapp.bizport.cn/”+locationPath);
    files.add(fileObj);
    refreshObj.put(“Files”, files);
    int status = refreshCDN(refreshObj.toJSONString());
    if(status != 200) {
    log.info(“刷新CDN缓存失败”);
    }
    return new ModelResult<>(Boolean.TRUE);
    }

    /**

    • 刷新CDN缓存

    • 参考链接: https://docs.ksyun.com/documents/215

    • @param dealFiles 待处理文件/文件夹

    •  {"Files":[{"Url":"http://test.dxz.ksyun.8686c.com/abc.txt"}],"Dirs":[{"Url":"https://cdn-qapp.bizport.cn/images"}]} 
    • @return 状态码
      */
      private int refreshCDN(String dealFiles) throws UnirestException {
      String uri = “/2016-09-01/content/RefreshCaches”;
      String accessKey = ks3Config.getAccessKey();
      String secretKey = ks3Config.getSecretKey();

      TreeMap<String, String> params = new TreeMap<String, String>();
      params.put(“Content-Type”, “application/json”);
      params.put(“Action”, “RefreshCaches”);
      params.put(“Version”, “2016-09-01”);
      params.put(“Accept”, “application/json”);

      TreeMap<String, String> awsHeaders = new TreeMap<String, String>();
      awsHeaders.put(“Host”, “cdn.api.ksyun.com”);
      awsHeaders.put(“Content-Length”, “”+ StringUtils.length(dealFiles));
      awsHeaders.put(“Content-Type”, “application/json”);
      awsHeaders.put(“X-Amz-Date”, getTimeStamp());

      Map<String, String> header = new AWSAuth.Builder(accessKey, secretKey)
      .regionName(“cn-beijing-6”)
      .serviceName(“cdn”)
      .httpMethodName(“POST”)
      .canonicalURI(uri)
      .queryParametes(params)
      .awsHeaders(awsHeaders)
      .payload(dealFiles)
      .debug()
      .build()
      .getHeaders1();

      HttpResponse response = Unirest.post(“http://cdn.api.ksyun.com/2016-09-01/content/RefreshCaches?Content-Type=application%2Fjson&Action=RefreshCaches&Version=2016-09-01&Accept=application%2Fjson”)
      .header(“content-type”, “application/json”)
      .header(“host”, “cdn.api.ksyun.com”)
      .header(“x-amz-date”, header.get(“x-amz-date”))
      .header(“authorization”, header.get(“Authorization”))
      .body(dealFiles)
      .asString();

      return response.getStatus();
      }

    private String getTimeStamp() {
    DateFormat dateFormat = new SimpleDateFormat(“yyyyMMdd’T’HHmmss’Z’”);
    dateFormat.setTimeZone(TimeZone.getTimeZone(“UTC”));
    return dateFormat.format(new Date());
    }

原文链接:https://blog.csdn.net/weixin_42649343/article/details/104313533?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522165918469516782390592771%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fblog.%2522%257D&request_id=165918469516782390592771&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~blog~first_rank_ecpm_v1~times_rank-27-104313533-null-null.nonecase&utm_term=%E9%A6%99%E6%B8%AFcdn

原创文章,作者:优速盾-小U,如若转载,请注明出处:https://www.cdnb.net/bbs/archives/4660

(0)
上一篇 2022年7月30日 22:04
下一篇 2022年7月30日 22:05

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注

优速盾注册领取大礼包www.cdnb.net
/sitemap.xml