SpringBoot集成腾讯COS流程

1.pom.xml中添加cos配置

XML 复制代码
<!--腾讯cos -->
<dependency>
	<groupId>com.qcloud</groupId>
	<artifactId>cos_api</artifactId>
	<version>5.6.28</version>
</dependency>

2.application.yaml中添加cos配置

java 复制代码
# 腾讯云存储cos相关公共配置
tencent:
  cos:
    secretId: ABIDFG5gz36gMp2xbyHvYw3u
    secretKey: 93ima8OcaHhDUUDjEdmfYEd
    bucketName: haha-18888888
    folder: video
    region: ap-shanghai

3.创建属性映射类CosProperties

java 复制代码
/**
 * Cos配置
 */
@Data
@Component
@RefreshScope
@ConfigurationProperties(prefix = "tencent.cos")
public class CosProperties {

    private String secretId;
    private String secretKey;
    private String bucketName;
    private String folder;
    private String region;

}

4.封装Cos工具类

java 复制代码
/**
 * cos 工具类
 */
@Slf4j
public class CosUtils {
    private static CosUtils cosUtils = new CosUtils();

    private COSClient cosClient;


    public static CosUtils getInstance() {
        return cosUtils;
    }

    private CosProperties cosProperties;

    public CosUtils setCosProperties(CosProperties cosProperties) {
        this.cosProperties = cosProperties;
        this.cosClient = createCOSClient(cosProperties);
        return this;
    }

    public String getUploadTemporaryToken(String key) {
        if (StrUtil.hasBlank(cosProperties.getSecretId(), cosProperties.getSecretKey())) {
            return null;
        }
        COSCredentials cred = new BasicCOSCredentials(cosProperties.getSecretId(), cosProperties.getSecretKey());
        COSSigner signer = new COSSigner();
        // 设置过期时间为1个小时
        LocalDateTime now = LocalDateTime.now();
        Date expiredTime = new Date(now.toInstant(ZoneOffset.of("+8")).toEpochMilli() + 3600L * 1000L);
        // 要签名的 key, 生成的签名只能用于对应此 key 的上传
        log.info("待签名key[{}], now[{}]", key, now);
        String signStr = signer.buildAuthorizationStr(HttpMethodName.PUT, key, cred, expiredTime);
        log.info("签名成功, key[{}], now[{}], signStr[{}]", key, now, signStr);
        return signStr;
    }


    /**
     * 上传文件
     * 1.创建本地文件 2.上传
     *
     * @param fileName    文件名(带后缀)
     * @param fileContent 文件内容
     * @return
     */
    public String upload(String fileName, String fileContent, String customizeFolder) {
        try {
            String cosSecretId = cosProperties.getSecretId();
            String cosSecretKey = cosProperties.getSecretKey();
            String folder = StringUtils.isEmpty(customizeFolder) ? cosProperties.getFolder() : customizeFolder;
            String bucketName = cosProperties.getBucketName();

            if (StringUtils.isEmpty(cosSecretId) ||
                    StringUtils.isEmpty(cosSecretKey) ||
                    StringUtils.isEmpty(bucketName) ||
                    StringUtils.isEmpty(folder)) {
                log.error("cos upload params Incomplete");
                return "";
            }

            String root = Objects.requireNonNull(CosUtils.class.getResource("/")).getPath();
            String s = root + "/temp/upload/";
            File localFile = getLocalFile(fileContent, s, fileName);
            if (localFile == null) {
                return "";
            }
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
            String fromatDate = LocalDateTime.now().format(formatter);
            String fileUrl = folder + "/" + fromatDate + "/" + fileName;

            PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, fileUrl, localFile);
            // 设置存储类型, 默认是标准(Standard), 低频(standard_ia)
            putObjectRequest.setStorageClass(StorageClass.Standard);
            try {
                this.cosClient.putObject(putObjectRequest);
            } catch (CosClientException e) {
                log.error("An exception occurs during execution cos upload,error message:{}", e.getMessage());
            }
            //删除本地缓存文件
            if (localFile.exists()) {
                localFile.delete();
            }
            return fileUrl.startsWith("/") ? fileUrl : "/" + fileUrl;
        }catch (Exception e){
            log.error("文件上传失败,{}",e);
        }
        return StrUtil.EMPTY;
    }

    /**
     * 删除文件
     *
     * @param bucketName
     * @param key
     * @return
     */
    public Boolean deleteCosFile(String bucketName, String key) {
        String cosSecretId = cosProperties.getSecretId();
        String cosSecretKey = cosProperties.getSecretKey();
        Boolean executeFlag = true;

        if (StringUtils.isEmpty(cosSecretId) ||
                StringUtils.isEmpty(cosSecretKey) ||
                StringUtils.isEmpty(bucketName) ||
                StringUtils.isEmpty(key)) {

            log.error("cos delete file  params Incomplete");

            return false;
        }

        COSCredentials cred = new BasicCOSCredentials(cosSecretId, cosSecretKey);
        // 2 设置bucket的区域, COS地域的简称请参照 https://www.qcloud.com/document/product/436/6224
        ClientConfig clientConfig = new ClientConfig(new Region("ap-nanjing"));
        // 3 生成cos客户端
        COSClient cosclient = new COSClient(cred, clientConfig);
        try {
            cosclient.deleteObject(bucketName, key);

        } catch (CosClientException e) {
            log.error("An exception occurs during execution cos delete,error message:{}", e.getMessage());
            executeFlag = false;
        }

        // 关闭客户端
        cosclient.shutdown();

        return executeFlag;
    }

    private void getDir(String path) {
        File localFile = new File(path);
        if (!localFile.exists()) {
            localFile.mkdirs();
        }
    }


    private File getLocalFile(String instructionSet, String dir, String fileName) {
        File localFile = null;
        try {

            getDir(dir);

            localFile = new File(dir, fileName);
            if (!localFile.exists()) {
                localFile.createNewFile();
            }
            FileOutputStream fos = new FileOutputStream(localFile, true);
            OutputStreamWriter osw = new OutputStreamWriter(fos);
            BufferedWriter bw = new BufferedWriter(osw);
            bw.write(instructionSet);
            bw.newLine();
            bw.flush();
            bw.close();
            osw.close();
            fos.close();

            return localFile;
        } catch (IOException e2) {
            log.error("An exception occurs during execution create local file,error message:{} ", e2.getMessage());
            return null;
        }
    }

    /**
     * 获取二进制文件
     */
    public static byte[] downLoadBinary(String urlStr) throws IOException {
        HttpURLConnection conn = null;
        InputStream inputStream = null;
        ByteArrayOutputStream bos = null;
        try {
            URL url = new URL(urlStr);
            conn = (HttpURLConnection) url.openConnection();
            //设置超时间为10秒
            conn.setConnectTimeout(10 * 1000);
            conn.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.135 Safari/537.36");
            //得到输入流
            inputStream = conn.getInputStream();
            bos = new ByteArrayOutputStream();
            //获取数据数组
            return readInputStream(inputStream, bos);
        } finally {
            if (bos != null) {
                bos.close();
            }
            if (inputStream != null) {
                inputStream.close();
            }
            if (conn != null) {
                conn.disconnect();
            }
        }
    }


    /**
     * 获取字符串列表
     */
    public static List<String> downLoadList(String urlStr) throws IOException {
        HttpURLConnection conn = null;
        InputStream inputStream = null;
        try {
            URL url = new URL(urlStr);
            conn = (HttpURLConnection) url.openConnection();
            //设置超时间为10秒
            conn.setConnectTimeout(10 * 1000);
            conn.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.135 Safari/537.36");
            //得到输入流
            inputStream = conn.getInputStream();
            //获取数据数组 windows操作系统默认编码:GB18030
            return IoUtil.readLines(new InputStreamReader(inputStream, Charset.forName("GB18030")), new ArrayList<>());
        } catch (IOException e){
            log.error("An exception occurs during execution download file,error message:{} ", e.getMessage());
            return Collections.EMPTY_LIST;
        }finally {
            if (inputStream != null) {
                inputStream.close();
            }
            if (conn != null) {
                conn.disconnect();
            }
        }
    }
    /**
     * 输入流转二进制
     */
    public static byte[] readInputStream(InputStream inputStream, ByteArrayOutputStream bos) throws IOException {
        byte[] buffer = new byte[1024];
        int len = 0;
        while ((len = inputStream.read(buffer)) != -1) {
            bos.write(buffer, 0, len);
        }
        return bos.toByteArray();
    }

    /**
     * 创建cosClient
     *
     * @param cosProperties
     * @return
     */
    public static COSClient createCOSClient(CosProperties cosProperties) {
        // 1 初始化用户身份信息(secretId, secretKey)。
        // SECRETID和SECRETKEY请登录访问管理控制台 https://console.cloud.tencent.com/cam/capi
        // 进行查看和管理
        String secretId = cosProperties.getSecretId();
        String secretKey = cosProperties.getSecretKey();
        COSCredentials cred = new BasicCOSCredentials(secretId, secretKey);
        // 2 设置 bucket 的地域, COS 地域的简称请参照
        // https://cloud.tencent.com/document/product/436/6224
        // clientConfig 中包含了设置 region, https(默认 http), 超时, 代理等 set 方法, 使用可参见源码或者常见问题
        // Java SDK 部分。
        Region region = new Region(cosProperties.getRegion());
        ClientConfig clientConfig = new ClientConfig(region);
        // 这里建议设置使用 https 协议
        // 从 5.6.54 版本开始,默认使用了 https
        clientConfig.setHttpProtocol(HttpProtocol.https);

        // 3 生成 cos 客户端。
        return new COSClient(cred, clientConfig);
    }

    /**
     * 获取视频属性: (宽度、高度、时长)
     * 获取方式:从oss获取
     *
     * @param ossUrl
     * @return
     */
    public VideoProperties getVideoPropertiesFromCos(String ossUrl) {
        try {
            // 此处的key为对象键,对象键是对象在存储桶内的唯一标识
            String key = ossUrl;
            GeneratePresignedUrlRequest req = new GeneratePresignedUrlRequest("greatpan-1300159541", key, HttpMethodName.GET);
            // 设置签名过期时间(可选), 若未进行设置, 则默认使用 ClientConfig 中的签名过期时间(1小时)
            // 可以设置任意一个未来的时间,推荐是设置 10 分钟到 3 天的过期时间
            // 这里设置签名在半个小时后过期
            Date expirationDate = new Date(System.currentTimeMillis() + 30L * 60L * 1000L);
            req.setExpiration(expirationDate);
            req.addRequestParameter("ci-process", "videoinfo");
            URL url = this.cosClient.generatePresignedUrl(req);
            String mediaInfoXml = HttpClientUtil.doGet(url.toString());
            if (mediaInfoXml != null) {
                Document document = XmlUtil.readXML(mediaInfoXml);
                Node error = document.getElementsByTagName("Error").item(0);
                if (!ObjectUtils.isEmpty(error)) {
                    Node message = document.getElementsByTagName("Message").item(0);
                    log.error("获取视频基础信息出错.ossurl:{}, e:{}", ossUrl, Optional.ofNullable(message).map(Node::getTextContent).orElse(""));
                    return null;
                }
                String width = document.getElementsByTagName("Width").item(0).getTextContent();
                String height = document.getElementsByTagName("Height").item(0).getTextContent();
                String rotation = document.getElementsByTagName("Rotation").item(0).getTextContent();
                if (StringUtils.isEmpty(width) || StringUtils.isEmpty(height) || StringUtils.isEmpty(rotation)) {
                    return null;
                }
                VideoProperties videoProperties = new VideoProperties();
                int w = Integer.parseInt(width);
                int h = Integer.parseInt(height);
                int r = (int) Double.parseDouble(rotation);
                // 如果r是90或者270, 说明视频有旋转操作, 并宽高比有变化,需要把w 和 h 调换
                if (r % 90 == 0 && (r / 90 % 2) == 1) {
                    videoProperties.setHeight(w);
                    videoProperties.setWidth(h);
                    return videoProperties;
                }
                videoProperties.setHeight(h);
                videoProperties.setWidth(w);
                return videoProperties;
            }
            return null;
        } catch (Exception e) {
            log.error("获取视频基础信息出错.ossurl:{}, e:", ossUrl, e);
            return null;
        }
    }

    public static void main(String[] args) throws Exception {
//        VideoProperties videoPropertiesFromCos = getVideoPropertiesFromCos("/video/2024-05-30/723d5de3-f874-4744-819f-0a31e6e8e507.mp4");
//        System.out.println(videoPropertiesFromCos);
        byte[] bytes = CosUtils.downLoadBinary("http://fs.haha.com/video/2024-05-30/1484098659191754752.txt");
        System.out.println(new String(bytes));
    }
}

5.前端获取cos上传token

java 复制代码
@Resource
private CosUtils cosUtils;

@GetMapping("/token")
@ApiOperation("获取文件存储token")
public ApiResponse<?> getFileUploadToken(@RequestParam String fileFullPath) {
	if(StringUtils.isEmpty(fileFullPath)){
		return ApiResponse.error("参数错误");
	}
	return ApiResponse.ok(cosUtils.getUploadTemporaryToken(fileFullPath));
}
相关推荐
Oxye15 分钟前
基于Springboot的运行时动态可调的定时任务
java·spring boot·后端
辣椒日记23 分钟前
各种排序算法【持续更新中.....】
java·算法·排序算法
zzzzzzzz'23 分钟前
浅谈 Mybatis 框架
数据库·mysql·mybatis
liuliuliuliuyujie1 小时前
缓冲流练习
java
姜君竹1 小时前
安卓碎片Fragment
android·java·开发语言·学习·ui
张天龙1 小时前
【SpringBoot】Java对象级联校验
java·spring boot
醉颜凉1 小时前
自旋锁(Spinlock):轻量级锁机制
java·面试·线程··自旋锁·非阻塞锁·检查锁状态
深夜无眠T1 小时前
JVM详解(个人学习笔记)
java·jvm·笔记·学习
lifelalala1 小时前
IDEA控制台中文乱码
java·ide·intellij-idea
垒咚一夏1 小时前
SpringMVC02
java·开发语言