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));
}
相关推荐
1 9 J几秒前
Java 上机实践4(类与对象)
java·开发语言·算法
Code apprenticeship1 分钟前
Java面试题(2)
java·开发语言
憨子周1 小时前
2M的带宽怎么怎么设置tcp滑动窗口以及连接池
java·网络·网络协议·tcp/ip
霖雨3 小时前
使用Visual Studio Code 快速新建Net项目
java·ide·windows·vscode·编辑器
SRY122404193 小时前
javaSE面试题
java·开发语言·面试
Fiercezm3 小时前
JUC学习
java
无尽的大道3 小时前
Java 泛型详解:参数化类型的强大之处
java·开发语言
ZIM学编程3 小时前
Java基础Day-Sixteen
java·开发语言·windows
我不是星海3 小时前
1.集合体系补充(1)
java·数据结构
P.H. Infinity4 小时前
【RabbitMQ】07-业务幂等处理
java·rabbitmq·java-rabbitmq